利用C語(yǔ)言實(shí)現(xiàn)五子棋游戲
本文實(shí)例為大家分享了C語(yǔ)言實(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ù)
先來(lái)看看運(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 //定義棋盤的長(zhǎng)
//定義常量方便全局的修改
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("請(qǐng)輸入:");
}
很簡(jiǎn)單,就不多說(shuō)了
四、初始化棋盤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ù)
打印簡(jiǎn)單的方格線,并打印數(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輸入不合法,則要對(duì)外部xy修改,所以選擇傳址操作
break;
}
else
{
printf("你不能在此處落子\n");
printf("玩家1落子,請(qǐng)重新輸入x y坐標(biāo): ");
scanf("%d%d", &x, &y);
}
}
else
{
printf("輸入坐標(biāo)不合法\n");
printf("玩家落子,請(qǐng)重新輸入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),能獲勝的地方必定是最后落子的水平線、豎直線、和兩個(gè)斜對(duì)角線,我們只需對(duì)其進(jìn)行檢索即可。ifwin的返回值決定之后的switch語(yǔ)句
弱弱的說(shuō)一句,雖然看起來(lái)多,但很多都是重復(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("請(qǐng)選擇模式:1.人機(jī);2.玩家對(duì)戰(zhàn)\n");
printf("請(qǐng)選擇:");
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("請(qǐng)重新輸入\n"); break;
}
} while (input != 1 && input != 2);//do while語(yǔ)句在輸入錯(cuò)誤時(shí)反復(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("玩家落子,請(qǐng)依次輸入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;
}
}
作者覺(jué)得寫的是挺啰嗦,歡迎留言建議。game2和game1玩家一的內(nèi)容很相近,就不贅述
九、作者遇到的坑點(diǎn)
1.輸入的坐標(biāo)和存在數(shù)組里的下標(biāo)有減一的關(guān)系,在寫的時(shí)候不要寫忘記了
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("請(qǐng)重新輸入\n"); break;
}
Sleep(3000);//暫停3秒
} while (input);//do while語(yǔ)句實(shí)現(xiàn)可以反復(fù)玩
return 0;
}
void menu()
{ //完成菜單的初始化
printf("***********************\n");
printf("***********************\n");
printf("*****1.play 0.exit****\n");
printf("***********************\n");
printf("***********************\n");
printf("請(qǐng)輸入:");
}
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("請(qǐng)選擇模式:1.人機(jī);2.玩家對(duì)戰(zhàn)\n");
printf("請(qǐng)選擇:");
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("請(qǐng)重新輸入\n"); break;
}
} while (input != 1 && input != 2);//do while語(yǔ)句在輸入錯(cuò)誤時(shí)反復(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("玩家落子,請(qǐng)依次輸入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落子,請(qǐng)輸入坐標(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落子,請(qǐng)輸入坐標(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輸入不合法,要對(duì)外部xy修改,所以要傳址操作
break;
}
else
{
printf("你不能在此處落子\n");
printf("玩家1落子,請(qǐng)重新輸入x y坐標(biāo): ");
scanf("%d%d", &x, &y);
}
}
else
{
printf("輸入坐標(biāo)不合法\n");
printf("玩家落子,請(qǐng)重新輸入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落子,請(qǐng)重新輸入x y坐標(biāo): ");
scanf("%d%d", &x, &y);
}
}
else
{
printf("輸入坐標(biāo)不合法\n");
printf("玩家落子,請(qǐng)重新輸入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;
}
如果對(duì)你有幫助和啟發(fā),作者感到很高興。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Cocos2d-x UI開發(fā)之CCControlButton控件類實(shí)例
這篇文章主要介紹了Cocos2d-x UI開發(fā)之CCControlButton控件類實(shí)例,本文代碼中包含大量注釋來(lái)講解CCControlButton控件類的使用,需要的朋友可以參考下2014-09-09
C++設(shè)計(jì)模式之迭代器模式(Iterator)
這篇文章主要為大家詳細(xì)介紹了C++設(shè)計(jì)模式之迭代器模式Iterator,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-04-04
OpenCV鼠標(biāo)繪制矩形和截取矩形區(qū)域圖像
這篇文章主要為大家詳細(xì)介紹了OpenCV鼠標(biāo)繪制矩形和截取矩形區(qū)域圖像,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-01-01
Visual Studio C++指針靠前靠后的問(wèn)題全面解析
這篇文章主要介紹了Visual Studio C++指針靠前靠后的問(wèn)題全面解析,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-04-04
C語(yǔ)言版學(xué)生成績(jī)管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言版學(xué)生成績(jī)管理系統(tǒng),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-01-01

