C語言實現簡單五子棋小遊戲
本文實例為大傢分享瞭C語言實現簡單五子棋小遊戲的具體代碼,供大傢參考,具體內容如下
效果圖如下:
設計思路:
棋盤設計為15×15格,初始狀態光標在棋盤的中央,白棋先走,輪流落子,當一方連成五子或下滿棋盤時,遊戲結束(連成五子的一方獲勝,下滿棋盤為和棋)。當遊戲一方勝利後顯示勝利信息,提示信息利用漢字點陣輸出。
程序遊戲是一個二維平面圖,可用二維數組來實現,數組兩個下標可以表示棋盤上的位置,數組元素的值代表棋格上的狀態,共有三種情況,分別是0代表空格,1代表白棋,2代表黑棋。程序的主要工作是接收棋手按鍵操作,棋手1用設定四個鍵控制光標移動,回車鍵表示落子。棋手2用另四個鍵控制光標移動,空格鍵表示落子。接收到回車鍵或空格鍵,說明棋手落子,先判斷是否是有效位置,即有棋子的位置不能重疊落子。落子成功後,馬上判斷以該位置為中心的八個方向:上、下、左、右、左上、左下、右上、右下是否有相同顏色的棋子連成五子,如果連成五子,則遊戲結束。
#include<stdio.h> #include<stdlib.h> #include<windows.h> #pragma comment(lib, "WINMM.LIB") #include <mmsystem.h> #include<conio.h> #include<time.h> #define width 32 //棋盤總寬度 #define high 31 //棋盤總高度 #define MAX_X 15 //棋盤橫向格子數 #define MAX_Y 15 //棋盤縱向格子數 #define WIDTH (16+width) //遊戲總高度 #define HIGH (high+4) //遊戲總高度 #define player1 1 //白子玩傢 #define player2 2 //黑子玩傢 #define emptyPlayer 0//無子 #define Unplayer -2 //中途退出遊戲,無玩傢獲勝 typedef struct Stack{ //記錄下每次落子的坐標 int x[MAX_X*MAX_Y]; int y[MAX_X*MAX_Y]; //相當於棧頂指針 int top; }Stack; int pos[MAX_X][MAX_Y];//存儲棋盤上各位置處的狀態 比如有白子為1, 有黑子為2,無子為0 int px,py; //光標位置 int player = 1;//記錄當前玩傢 默認玩傢從白方開始 int flag1 = 0;//標志遊戲開始 int gameOver_player = -1;//判斷結束的標志 int pre_px = -1, pre_py = -1;//記錄下上一次的坐標位置 void gotoxy(int x,int y);//設置CMD窗口光標位置 void hide_cursor(); //隱藏CMD窗口光標 void map();//打印地圖 void game_Description();//打印動態遊戲說明 void initMapState();//初始化遊戲位置數據 void mapState(int qizi);//數組記錄下對應位置的狀態 int isGoPlay();//判斷是否可以落子 int hasGoPlay(int Player);//以落子處為中心,判斷已經落子後的棋盤是否五子相連 void goPlay(int Player, Stack* p);//落子 Player 1 2 0 void yiDongKuang();//移動框 void player1_move();//玩傢1_移動 void player2_move();//玩傢2_移動 int gameOver();//判斷遊戲是否結束 Stack* createStack();//創建空棧 void push(Stack* p, int x, int y);//入棧 void color(const unsigned short textColor);//自定義函根據參數改變顏色 //void setColor(unsigned short backColor);//設置遊戲背景顏色 void gotoxy(int x,int y)//設置CMD窗口光標位置 { COORD coord; coord.X = x; coord.Y = y; SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord); } void hide_cursor() //隱藏CMD窗口光標 { CONSOLE_CURSOR_INFO cci; cci.bVisible = FALSE; cci.dwSize = sizeof(cci); HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE); SetConsoleCursorInfo(handle, &cci); } void color(const unsigned short textColor) //自定義函根據參數改變顏色 { if(textColor>0 && textColor<=15) //參數在0-15的范圍顏色 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), textColor); //用一個參數,改變字體顏色 else //默認的字體顏色是白色 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 7); } //打印地圖 void map() { int x, y; color(02); /*開始打印棋盤格子*/ //打印橫向圖格 for(y = 2; y < high - 1; y+=2){ for(x = 1; x < width - 2; x+=2){ gotoxy(x , y); printf("-+"); } } //打印豎向圖格 for(y = 1; y < high; y += 2) { for(x = 2; x < width-2; x += 2){ gotoxy(x , y); printf("|"); } } /*打印棋盤格子結束*/ /*開始打印圖框*/ //打印棋盤圖框 for (y = 0; y < high; y++) { for (x = 0; x < width; x+=2) { if (x == 0 || x == width - 2){ gotoxy(x, y); printf("|"); } if(y == 0 || y == high - 1 ){ gotoxy(x, y); printf("--"); } } } //打印右圖框 for(y = 0; y < high; y++){ for(x = width; x < WIDTH; x+=2){ if (x == WIDTH - 2){ gotoxy(x, y); printf("|"); } if(y == 0 || y == high - 1 ){ gotoxy(x, y); printf("--"); } } } //打印下圖框 y->high ~ HiGH-1 x->0 ~ WIDTH-2 for(y = high; y < HIGH; y++){ for(x = 0; x < WIDTH; x+=2){ if (x == 0 || x == WIDTH - 2){ gotoxy(x, y); printf("|"); } if(y == high || y == HIGH - 1 ){ gotoxy(x, y); printf("--"); } } } //打印下圖框內容 gotoxy( 1, high+1); printf(" 歡迎來到五子棋遊戲!"); //打印右圖框內容 gotoxy( width-1, 1); printf("遊戲說明:"); gotoxy( width-1, 3); printf("1)X表示玩傢一棋"); gotoxy( width-1, 4); printf("子,而O表示玩傢"); gotoxy( width-1, 5); printf("二棋子"); gotoxy( width-1, 7); printf("2)X先、O後,交替"); gotoxy( width-1, 8); printf("下子,每次隻能下"); gotoxy( width-1, 9); printf("一子"); gotoxy( width-1, 11); printf("3)棋子下在棋盤"); gotoxy( width-1, 12); printf("的格子內,棋子下"); gotoxy( width-1, 13); printf("定後,不得向其它"); gotoxy( width-1, 14); printf("點移動"); gotoxy( width-1, 16); printf("4)最先連成五子"); gotoxy( width-1, 17); printf("的一方即為獲勝"); gotoxy( width-1, 19); printf("玩傢一 移動鍵:"); gotoxy( width-1, 20); printf("w上 s下 a左 d右"); gotoxy( width-1, 21); printf("下子: 空格鍵"); gotoxy( width-1, 23); printf("玩傢二 移動鍵:"); gotoxy( width-1, 24); printf("i上 k下 j左 l右"); gotoxy( width-1, 25); printf("下子:回車鍵"); gotoxy( width+1, 27); color(4); printf("退出鍵: Y"); gotoxy( width+1, 29); color(6); printf("悔棋鍵: G"); /*打印圖框結束*/ color(02); /*打印棋盤上的四個標記點*/ gotoxy( 3*2+2 , 3*2+2); printf("*"); gotoxy( (MAX_X-4)*2 , 3*2+2); printf("*"); gotoxy( 3*2+2 , (MAX_Y-4)*2); printf("*"); gotoxy( (MAX_X-4)*2 , (MAX_Y-4)*2); printf("*"); /*打印結束*/ /*開始修邊*/ /*gotoxy(width - 1, 0); printf(" "); gotoxy(width - 1, high - 1); printf(" ");*/ /*修邊結束*/ /*打印地圖完成*/ } //打印動態遊戲說明 void game_Description() { //打印下圖框內容 gotoxy( 1, high+1); printf(" "); if(player == player1){ gotoxy( 1, high+1); color(2); printf(" 玩傢一下棋中..."); }else if(player == player2){ gotoxy( 1, high+1); color(2); printf(" 玩傢二下棋中..."); } } //初始化遊戲位置數據 void initMapState() { for(int i = 0 ; i < MAX_Y; i++){ for(int j = 0; j < MAX_X; j++){ pos[i][j] = 0;//初始狀態全為空 } } //註意 光標的位置和存儲在數組中的位置是不同的 px = 7; py = 7; gotoxy(py*2+1,px*2+1);//初始位置 } //數組記錄下對應位置的狀態 void mapState(int qizi) { //2*px+1 = x //2*py+1 = y //px->0~14 //py->0~14 if(px >= MAX_X || px < 0 || py >= MAX_Y || py < 0) return;//其他情況不可以記錄狀態 pos[px][py] = qizi; } //判斷是否可以落子 int isGoPlay() { if(px >= MAX_X || px < 0 || py >= MAX_Y || py < 0) return 0;//其他情況不可以記錄狀態 if(pos[px][py] == emptyPlayer){//說明無子 return 1; }else{//說明有子 return 0; } } //以落子處為中心,判斷已經落子後的棋盤是否五子相連 int hasGoPlay(int Player) { //分為兩部分,先記錄一部分的相同Player的個數 //再記錄下另餘部分的個數,相加為相連棋子總個數 int port1 = 0, port2 = 0; int x, y, count; //上下查找 x = px, y = py-1; while(pos[x][y]==Player && y >= 0){ ++port1;//上部分個數 --y;//上移 } y = py+1; while(pos[x][y]==Player && y < MAX_Y){ ++port2;//下部分個數 ++y;//下移 } //計算總數 count = port1 + port2 + 1; if(count >= 5) return 1; //左右查找 port1 = 0, port2 = 0; x = px-1, y = py; while(pos[x][y]==Player && x >= 0){ ++port1;//上部分個數 --x;//左移 } x = px+1; while(pos[x][y]==Player && x < MAX_X){ ++port2;//下部分個數 ++x;//右移 } //計算總數 count = port1 + port2 + 1; if(count >= 5) return 1; //左上右下查找 port1 = 0, port2 = 0; x = px-1, y = py-1; while(pos[x][y]==Player && x >= 0 && y >= 0){ ++port1;//上部分個數 --x;//左移 --y;//上移 } x = px+1, y = py+1; while(pos[x][y]==Player && x < MAX_X && y < MAX_Y){ ++port2;//下部分個數 ++x;//右移 ++y;//下移 } //計算總數 count = port1 + port2 + 1; if(count >= 5) return 1; //右上左下查找 port1 = 0, port2 = 0; x = px+1, y = py-1; while(pos[x][y]==Player && x < MAX_X && y >= 0){ ++port1;//上部分個數 ++x;//左移 --y;//上移 } x = px-1, y = py+1; while(pos[x][y]==Player && x >= 0 && y < MAX_Y){ ++port2;//下部分個數 --x;//右移 ++y;//下移 } //計算總數 count = port1 + port2 + 1; if(count >= 5) return 1; return 0; } //落子 Player 1 2 0 void goPlay(int Player, Stack* p) { if(isGoPlay()){//說明可以落子 mapState(Player);//將對應位置的情況記錄在數組中 if(hasGoPlay(Player)){//如果五子相連,則 gameover gameOver_player = Player; //記錄此刻勝利玩傢,結束遊戲 } /*入棧*/ push(p, px, py); /*角色切換*/ if(Player == player1){ player = player2;//切換成玩傢1 gotoxy(px*2+1, py*2+1 );//將光標移動到對應位置 color(07); printf("X");//打印玩傢1 game_Description();// 動態說明 }else if(Player == player2){ player = player1;//切換成另一個玩傢2 gotoxy( px*2+1, py*2+1);//將光標移動到對應位置 color(07); printf("O");//打印玩傢2 game_Description();// 動態說明 } } } //入棧 void push(Stack* p, int x, int y) { //將此刻的坐標入棧 int top = p->top; ++p->top;//移動棧針 p->x[top] = x; p->y[top] = y; return; } //出棧 void pop(Stack* p) { int x, y; //出棧,移動棧頂指針 //如果棧為空,則不彈出 if(p->top <= 0) return; --p->top; int top = p->top; //記錄下彈出的位置 x = p->x[top]; y = p->y[top]; //在彈出位置打印空格 gotoxy(x*2+1, y*2+1); printf(" "); //抹除記錄 pos[x][y] = 0; } //移動框 void yiDongKuang() { //打印移動框 gotoxy(px*2, py*2+1); color(11); printf("["); gotoxy(px*2+2, py*2+1); printf("]"); //打印移動框結束 if(pre_px != -1 && pre_py != -1){ if(pre_px > px && pre_py == py){//當向左移動時 //將上一個位置的右邊保持原樣 gotoxy(pre_px*2+2, pre_py*2+1); color(2); printf("|"); }else if(pre_px < px && pre_py == py){//當向右移動時 //將上一個位置的左邊保持原樣 gotoxy(pre_px*2, pre_py*2+1); color(2); printf("|"); }else{//當向上下移動時 //將上一個位置的左右邊保持原樣 gotoxy(pre_px*2+2, pre_py*2+1); color(2); printf("|"); gotoxy(pre_px*2, pre_py*2+1); color(2); printf("|"); } } pre_px = px; pre_py = py; } //玩傢1 移動 void player1_move(Stack* p) { char key; if (_kbhit())//檢測是否按鍵 { fflush(stdin); key = _getch();//保存按鍵 game_Description();//動態說明 } switch(key) { case 'w': py--;yiDongKuang();break;//上 case 'a': px--;yiDongKuang();break;//左 case 'd': px++;yiDongKuang();break;//右 case 's': py++;yiDongKuang();break;//下 case ' ': goPlay(player1, p);break;//落子 case 'y': gameOver_player = -2; gameOver();//退出遊戲 case 'Y': gameOver_player = -2; gameOver();//退出遊戲 case 'g': pop(p); pop(p); break;//悔棋 case 'G': pop(p); pop(p); break;//悔棋 default: break; } //限制光標范圍 if(py < 0) py = MAX_Y-1; else if(py >= MAX_Y) py = 0; else if(px < 0) px = MAX_X-1; else if(px >= MAX_X) px = 0; gotoxy(2*py+1, 2*px+1); } //玩傢2 移動 void player2_move(Stack* p) { char key; if (_kbhit())//檢測是否按鍵 { fflush(stdin); key = _getch();//保存按鍵 game_Description();//動態說明 } switch(key) { case 'i': py--;yiDongKuang();break;//上 case 'j': px--;yiDongKuang();break;//左 case 'l': px++;yiDongKuang();break;//右 case 'k': py++;yiDongKuang();break;//下 case '\r': goPlay(player2, p);break;//落子 case 'y': gameOver_player = -2; gameOver();//退出遊戲 case 'Y': gameOver_player = -2; gameOver();//退出遊戲 case 'g': pop(p); pop(p); break;//悔棋 case 'G': pop(p); pop(p); break;//悔棋 default: break; } //限制光標范圍 if(py < 0) py = MAX_Y-1; else if(py >= MAX_Y) py = 0; else if(px < 0) px = MAX_X-1; else if(px >= MAX_X) px = 0; gotoxy(2*px+1, 2*py+1); } //創建空棧 Stack* createStack(){ //申請空間 Stack* p = (Stack* )malloc(sizeof(Stack)); //如果未申請到空間 if(p==NULL) return NULL; p->top = 0;//初始化棧頂 return p; } //判斷遊戲是否結束 int gameOver() { //gamerOver_player -1 表示繼續遊戲 1 表示白方勝利 2 表示黑方勝利 0 表示平局 //五子相連 一方取勝 y->high ~ HiGH-1 x->0 ~ WIDTH-2 if(gameOver_player == -1){ return 1; }else if(gameOver_player == player1){//白方勝利 gotoxy( 1, high+1); printf("玩傢1勝利!!!"); return 0; }else if(gameOver_player == player2){//黑方勝利 gotoxy( 1, high+1); printf("玩傢2勝利!!!"); return 0; }else if(gameOver_player == emptyPlayer){//棋盤滿棋 平局 gotoxy( 1, high+1); printf("平局!!!"); return 0; }else if(gameOver_player == Unplayer){//中途退出 gotoxy( 1, high+1); printf("正在退出遊戲中..."); exit(1); } return 1; } int main(){ //調整遊戲框 system("mode con cols=48 lines=35"); //打印地圖 map(); //初始化遊戲位置數據 initMapState(); //創建空棧 Stack* p = createStack(); //隱藏光標 hide_cursor(); //遊戲循環 控制移動 while(gameOver()){ //不斷調換人物 if(player == player1) player1_move(p);// 切換玩傢1 else if(player == player2) player2_move(p);// 切換玩傢2 } free(p); }
以上就是本文的全部內容,希望對大傢的學習有所幫助,也希望大傢多多支持WalkonNet。