Skip to content

Instantly share code, notes, and snippets.

@taichunmin
Created June 19, 2014 05:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save taichunmin/d1dfe7350eaa01f72371 to your computer and use it in GitHub Desktop.
Save taichunmin/d1dfe7350eaa01f72371 to your computer and use it in GitHub Desktop.
╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳
╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳
╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳
╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳
╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳
╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳
╳╳ ╳╳
╳╳ ╳╳
╳╳ ╳╳
╳╳ ╳╳
╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳
╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳
╳╳ ╳╳
╳╳ ╳╳
╳╳ ╳╳
╳╳ ╳╳
/*
v0981006:
取消 reciprocal.h ,並將裡面的函式移進此程式碼內
v0980125:
計分版完成
增加多按幾下方向鍵可增加速度的功能
DATE:2009/3/19
v0971226:
改變遊戲畫面 (改成彩色)
障礙物地圖可由檔案讀取
v0971221:
將自定函式的本體全部移到 main() 之後
改變開始畫面 (改成彩色及方向鍵方式) (可塑性不高,待改)
縮小遊戲版面為 22*80 (預計加入記分版)
DATE:2008/12/21
*/
#include<iostream>
#include<fstream>
#include<ctime>
#include<conio.h>
#include<windows.h>
#define MAPLIST "maplist.txt"
#define MAP_PATH "map\\"
#define degree_of_difficulty 10000
#define MAX_MAIN_MENU 5
#define MAX_PAUSE_MENU 7
using namespace std;
//選單結構
typedef struct menu_node_type
{
string sa;
int sx;
int sy;
}menu_node;
int velocity=200;//速度 用於 Sleep() 函式的變數 越大越慢
int velo_list[10]={1000,790,580,475,370,265,160,125,90,55};//速度預設間距 velo_list[velo_ch]
int score;//分數
int step_count;//計步器
bool admin=0;//作弊模式
int setting[3]={0,5,0};//遊戲設定
HANDLE hStdOut;//gotoxy(),clrscr(),setcolor()
COORD scrn;
char bodysign[3]="○",headsign[3]="●",foodsign[3]="☆",blocksign[3]="╳";//各項代表符號
menu_node pause_menu[]={{"遊 戲 暫 停",30,8},
{"在這個畫面可以使用的指令有:",25,10},
{" exit | 結束遊戲",30,11},
{"option | 數值設定",30,12},
{"未輸入 | 繼續遊戲",30,13},
{"輸入完請按Enter",30,15},
{"->",27,16}};//暫停時的目錄
//需同時更改 show_color_board() 內的 max[]
void gotoxy(int,int);//移動游標
void setcolor(int,int);//設定顏色
void clrscr(void);//清空螢幕
void show_boardsign();//顯示邊界
void show_color_board(char [],int []);//以顏色輸出版面
void show_main_menu(int []);//顯示開始畫面
void font(int,int,int);//設定顏色及位置
int move_head(int*,int,char[],int[]);//移動頭
int pause_status();//暫停視窗
bool move_tail(int*,char[],int[]);//移動尾巴
bool change_setting(int);//更換設定
void show_score_board(int);//計分版
void show_num(int);
int main()
{
system("title 貪吃蛇 v0980125 BY 戴均民");
hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
int direct_replace_a[4]={80,75,77,72},direct_replace_b[4]={2,4,6,8};//下左右上
//0->遊戲模式 1->使用者的速度選擇 2->地圖列表
while(1)
{
srand(time(NULL));//設定亂數種子
//以下是變數宣告,設定
int direction=6;//方向 up8 down2 left4 right6
char ca;//用於接收按鍵
int head=4;//持久性的蛇頭座標 使用 head % 80 即為 x 座標 , 使用 head / 80 即為 y 座標
//這個變數的值必須位於 0 ~ 22*80 ( 1760 ) 之間 , 最後三行為記分板
int tail=0;//持久性的蛇尾座標
char board[1761]={"○○●"};//盤面顯示
int va[880]={1,2,3};//盤面紀錄
int food;//給蛇吃的食物 ☆
int food_count=0;//食物數量計數器
int vc=2;//儲存 move_tail() 所傳回的值
string sfilename="";//儲存地圖的檔名
score=0;//分數歸零
step_count=0;//計步器歸零
bool speedup=false;
show_main_menu(setting);//程式開場
//The game's source code field
//setting[2] 地圖讀取
if(setting[2]==1)
{
clrscr();
/*
string sa="MAPLIST";
int tfile_c=0;//地圖數
if(!fin)
{
MessageBox(NULL,"找不到地圖檔列表,\n請確認 map 資料夾內有 maplist.txt","錯誤",0);
setting[2]=0;
break;
}
fin>>tfile_c;
string* sb=new string[tfile_c];
for(int i=0;i<tfile_c;i++)getline(fin,sb[i]);
for(int i=0;i<tfile_c;i++)cout<<" "<<sb[i]<<endl;
*/
cout<<"請輸入檔名 -> ";
getline(cin,sfilename);
sfilename= MAP_PATH +sfilename;
ifstream fin(sfilename.c_str());
if(!fin)setting[2]=0;
if(setting[2]==1)
{
int ta,tb,tc;
while(fin>>ta>>tb>>tc)
if((0<=ta && ta<=79) && (0<=tb && tb<=21) && (-2<=tc && tc<=-1) && va[tb*40+ta]==0)
{
va[tb*40+ta]=tc;
switch(tc)
{
case -1:
board[tb*80+ta*2]=foodsign[0],board[tb*80+ta*2+1]=foodsign[1];
break;
case -2:
board[tb*80+ta*2]=blocksign[0],board[tb*80+ta*2+1]=blocksign[1];
break;
}
}
}
//地圖讀取結束
}
for(int i=6;i<1760;i++)
if(board[i]==0)board[i]=' ';//以空白填充盤面
//setting[0] 遊戲模式
switch(setting[0])
{
case 1:
int tempa=rand()%(440-3);
for(int i=3;i<tempa;i++)
{
food_count++;
food=rand()%880;
if(va[food]!=0)food_count--,i--;
else
{
va[food]=-1;
board[food*2]=foodsign[0],board[food*2+1]=foodsign[1];
}
}
break;
}
if(setting[0]==2)return 0;
velocity=velo_list[setting[1]];//setting[1] 速度
//倒數
clrscr();
for(int i=3;i>0;i--)
{
show_num(i);
Sleep(750);
clrscr();
}
show_color_board(board,va);
//system("pause");
show_score_board(3);
while(1)
{
if(kbhit())//接收所按的按鍵
{
ca=getch();
if(ca==13)
{
while(kbhit())getch();
switch(pause_status())
{
case 1:
return 0;
case 2:
admin=!admin;
break;
case 3:
int choose1;
do
{
clrscr();
cout<<"數值設定:"<<endl;
cout<<" |"<<endl;
cout<<" 1.速度 | 目前: "<<velocity<<endl;
cout<<" 0.退出 |"<<endl;
cout<<" |"<<endl;
cout<<endl;
cout<<"請輸入 -> ";
choose1=0;
cin>>choose1;
}while(change_setting(choose1));
break;
}
clrscr();
show_color_board(board,va);
show_score_board(3);
}
if(ca==-32)
{
ca=getch();
for(int i=0;i<4;i++)
if(ca==direct_replace_a[i])
{
if(direction!=direct_replace_b[i])direction=direct_replace_b[i];
else speedup=true;
break;
}
}
}
if(!food_count)
{
do{
food_count++;
food=rand()%880;
if(va[food]!=0)food_count--;
else
{
va[food]=-1;
board[food*2]=foodsign[0],board[food*2+1]=foodsign[1];
gotoxy((food*2%80),(food*2)/80);
font(-1,-1,5);
cout<<foodsign;
font(-1,-1,0);
}
}while(!food_count);
}
int vc=move_head(&head,direction,board,va);
step_count++;
if(vc==0)break;
else if(vc==1)
{
food_count--;
score+=setting[1]+step_count/100;
show_score_board(2);
}
else if(vc==2)move_tail(&tail,board,va);
if(speedup)speedup=false;
else Sleep(velocity);//過渡用變數
}
font(40,23,2);
cout<<"遊戲結束 , ";
Sleep(500);
system("pause");
clrscr();
}
}
//==============================================================================
void gotoxy(int xpos, int ypos)
{
//COORD scrn;
//HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
scrn.X = xpos; scrn.Y = ypos;
SetConsoleCursorPosition(hStdOut,scrn);
}
void setcolor(int f=7,int b=0)
{ //f 和 b 參數傳遞形式 i*8+j
//其中i為亮暗的差別,j為顏色
// 黑 藍 綠 青 紅 紫 黃 白
unsigned short ForeColor=f+16*b;
SetConsoleTextAttribute(hStdOut,ForeColor);
}
void clrscr(void)
{
font(0,0,0);
for(int i=0;i<2000;i++)printf(" ");
font(0,0,0);
}
int move_head(int *head,int direction,char board[],int va[])
{
int x=*head%80,y=*head/80;
bool eat_food=false;
if(direction==2 && y>=22)return 0;
else if(direction==4 && x<=0)return 0;
else if(direction==6 && x>=78)return 0;//因為使用雙字元 ■▉
else if(direction==8 && y<=0)return 0;
if(direction==2)*head+=80;
else if(direction==4)*head-=2;
else if(direction==6)*head+=2;
else if(direction==8)*head-=80;
if(board[*head]==foodsign[0] && board[*head+1]==foodsign[1])eat_food=true;
else if(board[*head]!=' ' && board[*head+1]!=' ')return 0;//撞到身體
int temp=va[40*y+x/2],vb=(*head/80)*40+*head%80/2;
if(temp< degree_of_difficulty )va[vb]=temp+1;
else
{
va[vb]=1;
if(velocity>60)velocity-=10;//速度遞減
}
board[80*y+x]=bodysign[0],board[80*y+x+1]=bodysign[1];
board[*head]=headsign[0],board[*head+1]=headsign[1];
font(x,y,4);
cout<<bodysign;
font(*head%80,*head/80,3);
cout<<headsign;
font(-1,-1,0);
if(eat_food)return 1;
return 2;
}
bool move_tail(int *tail,char board[],int va[])
{
int x=*tail%80,y=*tail/80;
int direction=0;//標示移動的方向
//找尋方向
if(va[40*y+x/2]+1==va[40*(y-1)+x/2] ||
(va[40*y+x/2]+1== degree_of_difficulty && va[40*(y-1)+x/2]==1))
direction=8;
else if(va[40*y+x/2]+1==va[40*(y+1)+x/2] ||
(va[40*y+x/2]+1== degree_of_difficulty && va[40*(y+1)+x/2]==1))
direction=2;
else if(va[40*y+x/2]+1==va[40*y+(x/2-1)] ||
(va[40*y+x/2]+1== degree_of_difficulty && va[40*y+(x/2-1)]==1))
direction=4;
else if(va[40*y+x/2]+1==va[40*y+(x/2+1)] ||
(va[40*y+x/2]+1== degree_of_difficulty && va[40*y+(x/2+1)]==1))
direction=6;
if(direction==2)*tail+=80;
else if(direction==8)*tail-=80;
else if(direction==6)*tail+=2;
else if(direction==4)*tail-=2;
board[80*y+x]=' ',board[80*y+x+1]=' ';
gotoxy(x,y);
cout<<" ";
va[40*y+x/2]=0;
}
int pause_status()
{
int x,y,menu_count=4,choose=0,inputx=30,inputy=15;
string smenu[]={"","exit","taichunmin","option"};
string sa;
bool miss_input=true;
while(miss_input)
{
x=22,y=5;
gotoxy(x,y++);
cout<<"┌───────────────┐";gotoxy(x,y++);
cout<<"│ │";gotoxy(x,y++);
cout<<"│ 遊 戲 暫 停 │";gotoxy(x,y++);
cout<<"│ │";gotoxy(x,y++);
cout<<"│ 在這個畫面可以使用的指令有: │";gotoxy(x,y++);
cout<<"│ exit | 結束遊戲 │";gotoxy(x,y++);
cout<<"│ option | 數值設定 │";gotoxy(x,y++);
cout<<"│ 未輸入 | 繼續遊戲 │";gotoxy(x,y++);
cout<<"│ │";gotoxy(x,y++);
cout<<"│ 輸入完請按Enter │";gotoxy(x,y++);
cout<<"│ -> │";gotoxy(x,y++);//14 22
cout<<"│ │";gotoxy(x,y++);
cout<<"└───────────────┘";gotoxy(inputx,inputy);//輸入
getline(cin,sa);
for(int i=0;i<menu_count && miss_input;i++)
if(sa==smenu[i])miss_input=false,choose=i;
}
return choose;
}
bool change_setting(int choose1)
{
if(choose1<1 || choose1>1)return false;
string menu_name[]={"","速度"};
clrscr();
cout<<"你選 "<<menu_name[choose1]<<endl;
if(choose1==1)
{
cout<<"請輸入新的值 -> ";
cin>>velocity;
}
return true;
}
void show_boardsign()//顯示邊界
{
char boardsign[][3]={"╔","╦","╗","╠","╬","╣","╚","╩","╝","║","═"};//邊界 ,""
// 0 1 2 3 4 5 6 7 8 9 10
/*
╔═╦═╗
╠═╬═╣ ╔╦╗╠═╬╣╓╥╖╒╤╕║╚╩╝╟╫╢╙╨╜╞╪╡╘╧╛
╚═╩═╝
*/
font(0,0,0);
cout<<boardsign[0];
for(int i=1;i<39;i++)
{
font(-1,-1,-1);
cout<<boardsign[1];
}
cout<<boardsign[2];
gotoxy(0,23);
cout<<boardsign[6];
for(int i=1;i<39;i++)
{
font(-1,-1,-1);
cout<<boardsign[7];
}
cout<<boardsign[8];
for(int i=1;i<23;i++)
{
font(0,i,-1);
cout<<boardsign[3];
font(78,i,-1);
cout<<boardsign[5];
}
}
void show_main_menu(int setting[])//顯示開始畫面
{
menu_node main_menu[]={{"<< 貪吃蛇遊戲 >>",31,4},
{"遊 戲 模 式 :",24,8},
{"遊 戲 速 度 :",24,12},
{"遊 戲 地 圖 :",24,16},
{"請用上下左右進行選擇",28,21}};//主目錄
string setting_text[][25]={{"普通模式","食物模式","結束遊戲"},
{"0","1","2","3","4","5","6","7","8","9"},
{"無障礙物","讀取地圖"}};//遊戲選單
int sett_x_y[][2]={{46,8},{50,12},{46,16}};//{,},輸出所選設定的xy座標
int max[]={3,10,2};
char ca;//用於接收按鍵
int ia=0;//紀錄目前的選項
int leftsite=43,rightsite=55;//左右箭頭的輸出位置
//選單
show_boardsign();
for(int i=0;i<MAX_MAIN_MENU;i++)
{
gotoxy(main_menu[i].sx,main_menu[i].sy);
cout<<main_menu[i].sa;
}
for(int i=0;i<MAX_MAIN_MENU-2;i++)
{
font(sett_x_y[i][0],sett_x_y[i][1],-1);
cout<<setting_text[i][ setting[i] ];
}
font(main_menu[ia+1].sx-1,main_menu[ia+1].sy,1);
cout<<' '<<main_menu[ia+1].sa;
font(leftsite,main_menu[ia+1].sy,2);
cout<<"←";
font(rightsite,main_menu[ia+1].sy,-1);
cout<<"→";
font(79,24,0);//把游標藏起來
while(ca=getch())
{
if(ca==-32)
{
ca=getch();
if(ca==72 || ca==80)//上下
{
font(main_menu[ia+1].sx-1,main_menu[ia+1].sy,-1);
cout<<' '<<main_menu[ia+1].sa;
font(leftsite,main_menu[ia+1].sy,-1);
cout<<" ";
font(rightsite,main_menu[ia+1].sy,-1);
cout<<" ";
if(ca==72)ia+=MAX_MAIN_MENU-3;
else ia+=MAX_MAIN_MENU-1;
ia%=MAX_MAIN_MENU-2;
font(main_menu[ia+1].sx-1,main_menu[ia+1].sy,1);
cout<<' '<<main_menu[ia+1].sa;
font(leftsite,main_menu[ia+1].sy,2);
cout<<"←";
font(rightsite,main_menu[ia+1].sy,-1);
cout<<"→";
font(79,24,-1);//把游標藏起來
font(-1,-1,0);//清空顏色設定
}
else if(ca==75 || ca==77)//左右
{
if(ca==75)setting[ia]+=max[ia]-1;
else setting[ia]+=max[ia]+1;
setting[ia]%=max[ia];
font(sett_x_y[ia][0],sett_x_y[ia][1],-1);
cout<<setting_text[ia][ setting[ia] ];
}
}
else if(ca==13)
{
font(-1,-1,0);
gotoxy(leftsite,main_menu[ia+1].sy);
cout<<" ";
gotoxy(rightsite,main_menu[ia+1].sy);
cout<<" ";
return;
}
font(79,24,-1);//把游標藏起來
}
}
void show_score_board(int statis=1)//計分版
{
if(statis%2)
{
font(0,22,-1);
for(int i=0;i<40;i++)cout<<"═";
font(2,22,-1);
cout<<" 得 分 ";
font(22,22,-1);
cout<<"╦";
for(int i=23;i<25;i++)
{
font(22,i,-1);
cout<<"║";
}
font(26,22,-1);
cout<<" 小 提 示 ";
font(40,23,-1);
cout<<"若要暫停遊戲請按 Enter 鍵。";
}
if((statis/2)%2)
{
font(10,23,5);
cout.width(10);
cout<<score;
}
font(79,24,0);//把游標藏起來
}
void font(int x,int y,int type=-1)//設定顏色及位置
{
//f 和 b 參數傳遞形式 i*8+j
//其中i為亮暗的差別,j為顏色
// 黑 藍 綠 青 紅 紫 黃 白
// 0 1 2 3 4 5 6 7
static int font_data[][2]={
{7,0},//原始 0
{12,2},//選單名字 1
{12,14},//箭頭 2
{11,0},//蛇頭 3
{2,0},//蛇身 4
{14,0},//食物 5
{13,14}};//障礙物 6
static int now_font=0;
if(type>-1 && now_font!=type)
{
setcolor(font_data[type][0],font_data[type][1]);
now_font=type;
}
if(x>-1 && y>-1)gotoxy(x,y);
}
void show_color_board(char board[],int va[])
{
for(int i=0;i<880;i++)
{
switch(va[i])
{
case -2://障礙物
font(-1,-1,6);
break;
case -1://食物
font(-1,-1,5);
break;
case 0://空格
font(-1,-1,0);
break;
default:
if(board[2*i]==headsign[0] && board[2*i+1]==headsign[1])
font(-1,-1,3);//蛇頭
else if(board[2*i]==bodysign[0] && board[2*i+1]==bodysign[1])
font(-1,-1,4);//蛇身
else if(board[2*i]==blocksign[0] && board[2*i+1]==blocksign[1])
font(-1,-1,5);//障礙物
break;
}
cout<<board[2*i]<<board[2*i+1];
}
font(-1,-1,0);
}
void show_num(int a)
{
cout<<endl<<endl;
if(a==1)
{
cout<<" 111111"<<endl;
cout<<" 11111111"<<endl;
cout<<" 1111111111"<<endl;
cout<<" 111111111111"<<endl;
cout<<" 11111111111111"<<endl;
cout<<" 111111"<<endl;
cout<<" 111111"<<endl;
cout<<" 111111"<<endl;
cout<<" 111111"<<endl;
cout<<" 111111"<<endl;
cout<<" 111111"<<endl;
cout<<" 111111"<<endl;
cout<<" 111111"<<endl;
cout<<" 111111"<<endl;
cout<<" 111111"<<endl;
cout<<" 111111"<<endl;
cout<<" 111111"<<endl;
cout<<" 111111"<<endl;
cout<<" 1111111111111111111111"<<endl;
cout<<" 1111111111111111111111"<<endl;
}
else if(a==2)
{
cout<<" 2222222222 "<<endl;
cout<<" 22222222222222"<<endl;
cout<<" 222222 222222"<<endl;
cout<<" 222222 222222"<<endl;
cout<<" 222222 222222"<<endl;
cout<<" 222222"<<endl;
cout<<" 222222"<<endl;
cout<<" 222222"<<endl;
cout<<" 222222"<<endl;
cout<<" 222222"<<endl;
cout<<" 222222"<<endl;
cout<<" 222222"<<endl;
cout<<" 222222"<<endl;
cout<<" 222222"<<endl;
cout<<" 222222"<<endl;
cout<<" 222222"<<endl;
cout<<" 222222"<<endl;
cout<<" 222222"<<endl;
cout<<" 2222222222222222222222"<<endl;
cout<<" 2222222222222222222222 "<<endl;
}
else if(a==3)
{
cout<<" 333333333333"<<endl;
cout<<" 3333333333333333"<<endl;
cout<<" 333333 333333"<<endl;
cout<<" 333333 333333"<<endl;
cout<<" 333333 333333"<<endl;
cout<<" 333333"<<endl;
cout<<" 333333"<<endl;
cout<<" 333333"<<endl;
cout<<" 333333"<<endl;
cout<<" 33333333"<<endl;
cout<<" 33333333"<<endl;
cout<<" 333333"<<endl;
cout<<" 333333"<<endl;
cout<<" 333333"<<endl;
cout<<" 333333"<<endl;
cout<<" 333333 333333"<<endl;
cout<<" 333333 333333"<<endl;
cout<<" 333333 333333"<<endl;
cout<<" 3333333333333333"<<endl;
cout<<" 333333333333 "<<endl;
}
cout<<endl<<endl;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment