利用C語言實現(xiàn)五子棋游戲
本文實例為大家分享了C語言實現(xiàn)五子棋游戲的具體代碼,供大家參考,具體內(nèi)容如下
一、前言
本文將先介紹五子棋運行所需要的函數(shù),最后串聯(lián)成完整代碼。
我們需要實現(xiàn)的功能有:1.菜單menu函數(shù)
2.初始化棋盤Initboard函數(shù)
3.顯示棋盤Displayboard函數(shù)
4.實現(xiàn)人機(jī)、人人模式的選擇
5.落子函數(shù) playermove computermove
6.判斷輸贏ifwin函數(shù)
先來看看運行效果吧!

二、頭文件
#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] == ' ')//保證落子點為空
{
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)驗,能獲勝的地方必定是最后落子的水平線、豎直線、和兩個斜對角線,我們只需對其進(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的具體實現(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ī)的下棋
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)容很相近,就不贅述
九、作者遇到的坑點
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語句實現(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ī)的下棋
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] == ' ')//保證落子點為空
{
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] == ' ')//保證落子點為空
{
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)文章
FFmpeg實戰(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實現(xiàn)分離PCM數(shù)據(jù),感興趣的可以了解一下2023-02-02
解決Microsoft?Visual?C++?2010?Express?運行及調(diào)試問題
這篇文章主要介紹了解決Microsoft?Visual?C++?2010?Express?運行及調(diào)試問題,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下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-03
C++?OpenCV實現(xiàn)boxfilter方框濾波的方法詳解
box?filter的作用很簡單,即對局部區(qū)域求平均,并把值賦給某個點,一般我們賦給區(qū)域中心。本文將用C++實現(xiàn)boxfilter方框濾波,需要的可以了解一下2022-10-10

