利用C語言實(shí)現(xiàn)五子棋游戲
本文實(shí)例為大家分享了C語言實(shí)現(xiàn)五子棋游戲的具體代碼,供大家參考,具體內(nèi)容如下
一、前言
本文將先介紹五子棋運(yùn)行所需要的函數(shù),最后串聯(lián)成完整代碼。
我們需要實(shí)現(xiàn)的功能有:1.菜單menu函數(shù)
2.初始化棋盤Initboard函數(shù)
3.顯示棋盤Displayboard函數(shù)
4.實(shí)現(xiàn)人機(jī)、人人模式的選擇
5.落子函數(shù) playermove computermove
6.判斷輸贏ifwin函數(shù)
先來看看運(yùn)行效果吧!
二、頭文件
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <string.h> #include<time.h> #include<stdlib.h> #include<windows.h> #define ROW 10 //定義棋盤的寬 #define COL 10 //定義棋盤的長 //定義常量方便全局的修改 void Initboard(char board[ROW][COL], int row, int col); //初始化棋盤 void Displayboard(char board[ROW][COL], int row, int col); //展示棋盤 void Playermove_1(char board[ROW][COL], int row, int col,int*px,int *py); //玩家一下棋 void Playermove_2(char board[ROW][COL], int row, int col,int*px, int *py); //玩家二下棋 void computermove(char board[ROW][COL], int row, int col); //電腦下棋 void game1(char board[ROW][COL], int row, int col); //人機(jī)模式 void game2(char board[ROW][COL], int row, int col); //人人模式 int Ifwin(char board[ROW][COL], int row, int col, int x, int y); //判斷輸贏 int check_x(char board[ROW][COL], int row, int col, int x, int y); //判斷豎直五子 int check_y(char board[ROW][COL], int row, int col, int x, int y); //判斷水平五子 int check_xy_up(char board[ROW][COL], int row, int col, int x, int y); //判斷斜上五子 int check_xy_down(char board[ROW][COL], int row, int col, int x, int y); //判斷斜下五子
三、menu菜單函數(shù)
void menu() { //完成菜單的初始化 printf("***********************\n"); printf("***********************\n"); printf("*****1.play 0.exit****\n"); printf("***********************\n"); printf("***********************\n"); printf("請輸入:"); }
很簡單,就不多說了
四、初始化棋盤Initboard函數(shù)
初始化棋盤,為數(shù)組一一存入空格
void Initboard(char board[ROW][COL], int row, int col) { int i = 0; int j = 0; for (i = 0; i < row; i++) { for (j = 0; j < col; j++) { board[i][j] = ' '; } } }
五、顯示棋盤Displayboard函數(shù)
打印簡單的方格線,并打印數(shù)據(jù)內(nèi)容
void Displayboard(char board[ROW][COL], int row, int col) { int i = 0; int j = 0; for (j = 0; j < col; j++)//打印橫向y坐標(biāo) { if (j == 0)//考慮到x軸所占的一格 { printf(" %d ", j + 1); } else { printf(" %d ", j + 1); } } printf("\n"); for (i = 0; i < row; i++)//打印數(shù)據(jù) { for (j = 0; j < col; j++) { if (j == 0)//順帶打印豎向x坐標(biāo) { printf("%2d",i+1);//%md表示域?qū)挒閙 printf(" %c ",board[i][j]); } else { printf(" %c ", board[i][j]); } if (j < col - 1) printf("|"); } printf("\n"); //打印分割行 if (i < row - 1) { for (j = 0; j < col; j++) { if (j == 0)//同樣考慮到y(tǒng)軸 printf(" ---"); else printf("---"); if (j < col - 1) printf("|"); } printf("\n"); } } }
六、落子函數(shù)
玩家一落子——playermove_1
void Playermove_1(char board[ROW][COL], int row, int col, int *px, int*py)//ROW可以省,COL不行 { int x = *px; int y = *py; while (1) { if (x >= 1 && x <= row && y >= 1 && y <= col)//判斷輸入坐標(biāo)的合法性 { if (board[x -1][y- 1] == ' ')//保證落子點(diǎn)為空 { board[x-1 ][y -1] = '*'; *px = x; *py = y;//如果開始xy輸入不合法,則要對外部xy修改,所以選擇傳址操作 break; } else { printf("你不能在此處落子\n"); printf("玩家1落子,請重新輸入x y坐標(biāo): "); scanf("%d%d", &x, &y); } } else { printf("輸入坐標(biāo)不合法\n"); printf("玩家落子,請重新輸入x y坐標(biāo): "); scanf("%d%d", &x, &y); } } }
玩家2落子完全相同,就不贅敘了
電腦落子
void computermove(char board[ROW][COL], int row, int col) { int x = 0; int y = 0; //rand函數(shù)的使用需要srand函數(shù)的初始化,但srand不可以被重復(fù)調(diào)用,所以放在外部 while (1) { x = rand() % ROW; y = rand() % COL; if (board[x][y] == ' ')//x的范圍在0~row-1,所以這里x不用-1了 { board[x][y] = '#'; break; } } }
七、判斷輸贏ifwin
根據(jù)我們下五子棋的經(jīng)驗(yàn),能獲勝的地方必定是最后落子的水平線、豎直線、和兩個斜對角線,我們只需對其進(jìn)行檢索即可。ifwin的返回值決定之后的switch語句
弱弱的說一句,雖然看起來多,但很多都是重復(fù)的。
int Ifwin(char board[ROW][COL], int row, int col, int x, int y) { int ret; { ret = check_x(board, row, col, x, y); if (ret >= 5) return 0; ret = check_y(board, row, col, x, y); if (ret >= 5) return 0; ret = check_xy_up(board, row, col, x, y); if (ret >= 5) return 0; ret = check_xy_down(board, row, col, x, y); if (ret >= 5) return 0; } return 3; } int check_x(char board[ROW][COL], int row, int col, int x, int y)//檢查x軸豎直方向 { int sum = 1; int old_x = x; while (x < row && board[x - 1][y - 1] == board[x][y - 1]) { sum++; x++; } x = old_x; while (x-2>= 0 && board[x - 1][y - 1] == board[x - 2][y - 1] ) { sum++; x--; } return sum; } int check_y(char board[ROW][COL], int row, int col, int x, int y)//檢查y軸水平方向 { int sum = 1; int old_y = y; while (y<col && board[x-1][y-1] == board[x-1][y] ) { sum++; y++; } y = old_y; while (y-2 >= 0 && board[x-1][y-1] == board[x-1][y -2] ) { sum++; y--; } return sum; } int check_xy_up(char board[ROW][COL], int row, int col, int x, int y)//檢查斜上45度 { int sum = 1; int old_x = x; int old_y = y; while (x<row && y - 2 >= 0 && board[x - 1][y - 1] == board[x][y - 2]) { sum++; x++; y--; } x = old_x; y = old_y; while (x - 2 >= 0 && y <col && board[x - 1][y - 1] == board[x - 2][y]) { sum++; x--; y++; } return sum; } int check_xy_down(char board[ROW][COL], int row, int col, int x, int y)//檢查斜下45度 { int sum = 1; int old_x = x; int old_y = y; while (x<row && y <col && board[x - 1][y - 1] == board[x][y]) { sum++; x++; y++; } x = old_x; y = old_y; while (board[x-1][y-1] == board[x -2][y-2 ] && x-2>=0 && y-2 >=0) { sum++; x--; y--; } return sum; }
八、人機(jī)、人人模式的選擇
初始選擇界面
void game() { int input; char board[ROW][COL] = { 0 }; Initboard(board, ROW, COL); //初始化棋盤 Displayboard(board, ROW, COL); //展示棋盤 printf("請選擇模式:1.人機(jī);2.玩家對戰(zhàn)\n"); printf("請選擇:"); do{ scanf("%d", &input); printf("\n"); switch (input) { case 1:printf("游戲模式1開始!(注意:豎為x軸,橫為y軸)\n"); game1(board, ROW, COL); break; case 2:printf("游戲模式2開始!(注意:豎為x軸,橫為y軸)\n"); ; game2(board, ROW, COL); break; default:printf("請重新輸入\n"); break; } } while (input != 1 && input != 2);//do while語句在輸入錯誤時反復(fù)輸入 }
game1的具體實(shí)現(xiàn)
void game1(char board[ROW][COL], int row, int col) { srand((unsigned int)time(NULL));//srand只要設(shè)置一次就可以,所以要放在while循環(huán)外 while (1) { int ret; int count = 0; int flag = 0; //判讀玩家的下棋 int x; int y; printf("玩家落子,請依次輸入x y坐標(biāo): "); scanf("%d%d", &x, &y); Playermove_1(board, row, col,&x, &y); count++; Displayboard(board, ROW, COL); if (count == ROW*COL)//全下滿則認(rèn)為平局 ret = 1; else ret = Ifwin(board, ROW, COL, x, y); switch (ret) { case 0:printf("玩家獲勝\n"); flag = 1; break; case 1:printf("平局\n"); flag = 1; break; default: break; } if (flag == 1)//用flag跳出while循環(huán) break; //判斷計(jì)算機(jī)的下棋 computermove(board, row, col); count++; Displayboard(board, ROW, COL); if (count == ROW*COL) ret = 1; else ret = Ifwin(board, ROW, COL, x, y); switch (ret) { case 0:printf("電腦獲勝\n"); flag = 1; break; case 1:printf("平局\n"); flag = 1; break; default: break; } if (flag == 1) break; } }
作者覺得寫的是挺啰嗦,歡迎留言建議。game2和game1玩家一的內(nèi)容很相近,就不贅述
九、作者遇到的坑點(diǎn)
1.輸入的坐標(biāo)和存在數(shù)組里的下標(biāo)有減一的關(guān)系,在寫的時候不要寫忘記了
2.傳址操作才能改變函數(shù)外的變量值
十、完整的代碼
頭文件就省了
int main() { int input; do{ system("cls");//清屏 menu(); scanf("%d", &input); switch (input) { case 1: printf("游戲開始\n\n"); game(); break; case 0: printf("退出游戲\n"); break; default: printf("請重新輸入\n"); break; } Sleep(3000);//暫停3秒 } while (input);//do while語句實(shí)現(xiàn)可以反復(fù)玩 return 0; } void menu() { //完成菜單的初始化 printf("***********************\n"); printf("***********************\n"); printf("*****1.play 0.exit****\n"); printf("***********************\n"); printf("***********************\n"); printf("請輸入:"); } void Initboard(char board[ROW][COL], int row, int col) { int i = 0; int j = 0; for (i = 0; i < row; i++) { for (j = 0; j < col; j++) { board[i][j] = ' '; } } } void Displayboard(char board[ROW][COL], int row, int col) { int i = 0; int j = 0; for (j = 0; j < col; j++)//打印橫向y坐標(biāo) { if (j == 0)//考慮到x軸所占的一格 { printf(" %d ", j + 1); } else { printf(" %d ", j + 1); } } printf("\n"); for (i = 0; i < row; i++)//打印數(shù)據(jù) { for (j = 0; j < col; j++) { if (j == 0)//順帶打印豎向x坐標(biāo) { printf("%2d",i+1);//%md表示域?qū)挒閙 printf(" %c ",board[i][j]); } else { printf(" %c ", board[i][j]); } //數(shù)字表示坐標(biāo) if (j < col - 1) printf("|"); } printf("\n"); //打印分割行 if (i < row - 1) { for (j = 0; j < col; j++) { if (j == 0)//同樣考慮到y(tǒng)軸 printf(" ---"); else printf("---"); if (j < col - 1) printf("|"); } printf("\n");//別忘記這里也要換行 } } } void game() { int input; char board[ROW][COL] = { 0 }; Initboard(board, ROW, COL); //初始化棋盤 Displayboard(board, ROW, COL); //展示棋盤 printf("請選擇模式:1.人機(jī);2.玩家對戰(zhàn)\n"); printf("請選擇:"); do{ scanf("%d", &input); printf("\n"); switch (input) { case 1:printf("游戲模式1開始!(注意:豎為x軸,橫為y軸)\n"); game1(board, ROW, COL); break; case 2:printf("游戲模式2開始!(注意:豎為x軸,橫為y軸)\n"); ; game2(board, ROW, COL); break; default:printf("請重新輸入\n"); break; } } while (input != 1 && input != 2);//do while語句在輸入錯誤時反復(fù)輸入 } void game1(char board[ROW][COL], int row, int col) { srand((unsigned int)time(NULL));//srand只要設(shè)置一次就可以,所以要放在while循環(huán)外 while (1) { int ret; int count = 0; int flag = 0; //判讀玩家的下棋 int x; int y; printf("玩家落子,請依次輸入x y坐標(biāo): "); scanf("%d%d", &x, &y); Playermove_1(board, row, col,&x, &y); count++; Displayboard(board, ROW, COL); if (count == ROW*COL)//全下滿則認(rèn)為平局 ret = 1; else ret = Ifwin(board, ROW, COL, x, y); switch (ret) { case 0:printf("玩家獲勝\n"); flag = 1; break; case 1:printf("平局\n"); flag = 1; break; default: break; } if (flag == 1)//用flag跳出while循環(huán) break; //判斷計(jì)算機(jī)的下棋 computermove(board, row, col); count++; Displayboard(board, ROW, COL); if (count == ROW*COL) ret = 1; else ret = Ifwin(board, ROW, COL, x, y); switch (ret) { case 0:printf("電腦獲勝\n"); flag = 1; break; case 1:printf("平局\n"); flag = 1; break; default: break; } if (flag == 1) break; } } void game2(char board[ROW][COL], int row, int col) { while (1) { int ret; int count = 0; int flag = 0; int x; int y; //判讀玩家1的下棋 printf("玩家1落子,請輸入坐標(biāo):(注意:豎為x軸,橫為y軸)"); scanf("%d%d", &x, &y); Playermove_1(board, row, col, &x, &y); count++; Displayboard(board, ROW, COL); if (count == ROW*COL) ret = 1; else ret = Ifwin(board, ROW, COL, x, y); switch (ret) { case 0:printf("玩家1獲勝\n"); flag = 1; break; case 1:printf("平局\n"); flag = 1; break; default: break; } if (flag == 1) break; //判斷玩家2的下棋 printf("玩家2落子,請輸入坐標(biāo):(注意:豎為x軸,橫為y軸)"); scanf("%d%d", &x, &y); Playermove_2(board, row, col, &x, &y); count++; Displayboard(board, ROW, COL); if (count == ROW*COL) ret = 1; else ret = Ifwin(board, ROW, COL, x, y); switch (ret) { case 0:printf("玩家2獲勝\n"); flag = 1; break; case 1:printf("平局\n"); flag = 1; break; default: break; } if (flag == 1) break; } } void Playermove_1(char board[ROW][COL], int row, int col, int *px, int*py)//ROW可以省,COL不行 { int x = *px; int y = *py; while (1) { if (x >= 1 && x <= row && y >= 1 && y <= col)//判斷輸入坐標(biāo)的合法性 { if (board[x -1][y- 1] == ' ')//保證落子點(diǎn)為空 { board[x-1 ][y -1] = '*'; *px = x; *py = y;//如果開始xy輸入不合法,要對外部xy修改,所以要傳址操作 break; } else { printf("你不能在此處落子\n"); printf("玩家1落子,請重新輸入x y坐標(biāo): "); scanf("%d%d", &x, &y); } } else { printf("輸入坐標(biāo)不合法\n"); printf("玩家落子,請重新輸入x y坐標(biāo): "); scanf("%d%d", &x, &y); } } } void Playermove_2(char board[ROW][COL], int row, int col, int *px, int*py) { int x = *px; int y = *py; while (1) { if (x >= 1 && x <= row && y >= 1 && y <= col)//判斷輸入坐標(biāo)的合法性 { if (board[x - 1][y - 1] == ' ')//保證落子點(diǎn)為空 { board[x - 1][y - 1] = '#'; *px = x; *py = y; break; } else { printf("你不能在此處落子\n"); printf("玩家2落子,請重新輸入x y坐標(biāo): "); scanf("%d%d", &x, &y); } } else { printf("輸入坐標(biāo)不合法\n"); printf("玩家落子,請重新輸入x y坐標(biāo): "); scanf("%d%d", &x, &y); } } } void computermove(char board[ROW][COL], int row, int col) { int x = 0; int y = 0; while (1) { x = rand() % ROW; y = rand() % COL; if (board[x][y] == ' ') { board[x][y] = '#'; break; } } } int Ifwin(char board[ROW][COL], int row, int col, int x, int y) { int ret; { ret = check_x(board, row, col, x, y); if (ret >= 5) return 0; ret = check_y(board, row, col, x, y); if (ret >= 5) return 0; ret = check_xy_up(board, row, col, x, y); if (ret >= 5) return 0; ret = check_xy_down(board, row, col, x, y); if (ret >= 5) return 0; } return 3; } int check_x(char board[ROW][COL], int row, int col, int x, int y)//檢查x軸豎直方向 { int sum = 1; int old_x = x; while (x < row && board[x - 1][y - 1] == board[x][y - 1]) { sum++; x++; } x = old_x; while (x-2>= 0 && board[x - 1][y - 1] == board[x - 2][y - 1] ) { sum++; x--; } return sum; } int check_y(char board[ROW][COL], int row, int col, int x, int y)//檢查y軸水平方向 { int sum = 1; int old_y = y; while (y<col && board[x-1][y-1] == board[x-1][y] ) { sum++; y++; } y = old_y; while (y-2 >= 0 && board[x-1][y-1] == board[x-1][y -2] ) { sum++; y--; } return sum; } int check_xy_up(char board[ROW][COL], int row, int col, int x, int y)//檢查斜上45度 { int sum = 1; int old_x = x; int old_y = y; while (x<row && y - 2 >= 0 && board[x - 1][y - 1] == board[x][y - 2]) { sum++; x++; y--; } x = old_x; y = old_y; while (x - 2 >= 0 && y <col && board[x - 1][y - 1] == board[x - 2][y]) { sum++; x--; y++; } return sum; } int check_xy_down(char board[ROW][COL], int row, int col, int x, int y)//檢查斜下45度 { int sum = 1; int old_x = x; int old_y = y; while (x<row && y <col && board[x - 1][y - 1] == board[x][y]) { sum++; x++; y++; } x = old_x; y = old_y; while (board[x-1][y-1] == board[x -2][y-2 ] && x-2>=0 && y-2 >=0) { sum++; x--; y--; } return sum; }
如果對你有幫助和啟發(fā),作者感到很高興。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
C語言實(shí)現(xiàn)找出二叉樹中某個值的所有路徑的方法
這篇文章主要介紹了C語言實(shí)現(xiàn)找出二叉樹中某個值的所有路徑的方法,針對數(shù)據(jù)結(jié)構(gòu)中二叉樹的實(shí)用操作技巧,需要的朋友可以參考下2014-09-09FFmpeg實(shí)戰(zhàn)之分離出PCM數(shù)據(jù)
PCM(Pulse?Code?Modulation,脈沖編碼調(diào)制)音頻數(shù)據(jù)是未經(jīng)壓縮的音頻采樣數(shù)據(jù)裸流,它是由模擬信號經(jīng)過采樣、量化、編碼轉(zhuǎn)換成的標(biāo)準(zhǔn)數(shù)字音頻數(shù)據(jù)。本文將通過FFmpeg實(shí)現(xiàn)分離PCM數(shù)據(jù),感興趣的可以了解一下2023-02-02解決Microsoft?Visual?C++?2010?Express?運(yùn)行及調(diào)試問題
這篇文章主要介紹了解決Microsoft?Visual?C++?2010?Express?運(yùn)行及調(diào)試問題,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-01-01通過c語言調(diào)用系統(tǒng)curl動態(tài)庫的示例詳解
這篇文章中我們將通過一個簡單的示例來講解如何在Ubuntu系統(tǒng)中通過C語言調(diào)用動態(tài)庫(共享庫)的方法,我們將使用libcurl庫,這是一個基于客戶端的URL傳輸庫,廣泛用于各種程序和應(yīng)用中以訪問網(wǎng)頁和服務(wù)器數(shù)據(jù),需要的朋友可以參考下2024-03-03C++?OpenCV實(shí)現(xiàn)boxfilter方框?yàn)V波的方法詳解
box?filter的作用很簡單,即對局部區(qū)域求平均,并把值賦給某個點(diǎn),一般我們賦給區(qū)域中心。本文將用C++實(shí)現(xiàn)boxfilter方框?yàn)V波,需要的可以了解一下2022-10-10