目錄
一、前言
二、頭檔案
三、menu菜單函數
四、初始化棋盤Initboard函數
五、顯示棋盤Displayboard函數
六、落子函數
七、判斷輸赢ifwin
八、人機、人人模式的選擇
九、作者遇到的坑點
十、完整的代碼
一、前言
本文将先介紹五子棋運作所需要的函數,最後串聯成完整代碼。
我們需要實作的功能有:1.菜單menu函數
2.初始化棋盤Initboard函數
3.顯示棋盤Displayboard函數
4.實作人機、人人模式的選擇
5.落子函數 playermove computermove
6.判斷輸赢ifwin函數
先來看看運作效果吧!
二、頭檔案
#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);
//人機模式
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菜單函數
void menu()
{ //完成菜單的初始化
printf("***********************\n");
printf("***********************\n");
printf("*****1.play 0.exit****\n");
printf("***********************\n");
printf("***********************\n");
printf("請輸入:");
}
很簡單,就不多說了
四、初始化棋盤Initboard函數
初始化棋盤,為數組一一存入空格
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函數
列印簡單的方格線,并列印資料内容
void Displayboard(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (j = 0; j < col; j++)//列印橫向y坐标
{
if (j == 0)//考慮到x軸所占的一格
{
printf(" %d ", j + 1);
}
else
{
printf(" %d ", j + 1);
}
}
printf("\n");
for (i = 0; i < row; i++)//列印資料
{
for (j = 0; j < col; j++)
{
if (j == 0)//順帶列印豎向x坐标
{
printf("%2d",i+1);//%md表示域寬為m
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軸
printf(" ---");
else
printf("---");
if (j < col - 1)
printf("|");
}
printf("\n");
}
}
}
六、落子函數
玩家一落子——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)//判斷輸入坐标的合法性
{
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坐标: ");
scanf("%d%d", &x, &y);
}
}
else
{
printf("輸入坐标不合法\n");
printf("玩家落子,請重新輸入x y坐标: ");
scanf("%d%d", &x, &y);
}
}
}
玩家2落子完全相同,就不贅叙了
電腦落子
void computermove(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
//rand函數的使用需要srand函數的初始化,但srand不可以被重複調用,是以放在外部
while (1)
{
x = rand() % ROW;
y = rand() % COL;
if (board[x][y] == ' ')//x的範圍在0~row-1,是以這裡x不用-1了
{
board[x][y] = '#';
break;
}
}
}
七、判斷輸赢ifwin
根據我們下五子棋的經驗,能獲勝的地方必定是最後落子的水準線、豎直線、和兩個斜對角線,我們隻需對其進行檢索即可。ifwin的傳回值決定之後的switch語句
弱弱的說一句,雖然看起來多,但很多都是重複的。若要優化就使用函數指針
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;
}
八、人機、人人模式的選擇
初始選擇界面
void game()
{
int input;
char board[ROW][COL] = { 0 };
Initboard(board, ROW, COL);
//初始化棋盤
Displayboard(board, ROW, COL);
//展示棋盤
printf("請選擇模式:1.人機;2.玩家對戰\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語句在輸入錯誤時反複輸入
}
game1的具體實作
void game1(char board[ROW][COL], int row, int col)
{
srand((unsigned int)time(NULL));//srand隻要設定一次就可以,是以要放在while循環外
while (1)
{
int ret;
int count = 0;
int flag = 0;
//判讀玩家的下棋
int x; int y;
printf("玩家落子,請依次輸入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("玩家獲勝\n"); flag = 1; break;
case 1:printf("平局\n"); flag = 1; break;
default: break;
}
if (flag == 1)//用flag跳出while循環
break;
//判斷計算機的下棋
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玩家一的内容很相近,就不贅述
九、作者遇到的坑點
1.輸入的坐标和存在數組裡的下标有減一的關系,在寫的時候不要寫忘記了
2.傳址操作才能改變函數外的變量值
十、完整的代碼
頭檔案就省了
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語句實作可以反複玩
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坐标
{
if (j == 0)//考慮到x軸所占的一格
{
printf(" %d ", j + 1);
}
else
{
printf(" %d ", j + 1);
}
}
printf("\n");
for (i = 0; i < row; i++)//列印資料
{
for (j = 0; j < col; j++)
{
if (j == 0)//順帶列印豎向x坐标
{
printf("%2d",i+1);//%md表示域寬為m
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軸
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.人機;2.玩家對戰\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語句在輸入錯誤時反複輸入
}
void game1(char board[ROW][COL], int row, int col)
{
srand((unsigned int)time(NULL));//srand隻要設定一次就可以,是以要放在while循環外
while (1)
{
int ret;
int count = 0;
int flag = 0;
//判讀玩家的下棋
int x; int y;
printf("玩家落子,請依次輸入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("玩家獲勝\n"); flag = 1; break;
case 1:printf("平局\n"); flag = 1; break;
default: break;
}
if (flag == 1)//用flag跳出while循環
break;
//判斷計算機的下棋
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落子,請輸入坐标:(注意:豎為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落子,請輸入坐标:(注意:豎為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)//判斷輸入坐标的合法性
{
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坐标: ");
scanf("%d%d", &x, &y);
}
}
else
{
printf("輸入坐标不合法\n");
printf("玩家落子,請重新輸入x y坐标: ");
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)//判斷輸入坐标的合法性
{
if (board[x - 1][y - 1] == ' ')//保證落子點為空
{
board[x - 1][y - 1] = '#';
*px = x; *py = y;
break;
}
else
{
printf("你不能在此處落子\n");
printf("玩家2落子,請重新輸入x y坐标: ");
scanf("%d%d", &x, &y);
}
}
else
{
printf("輸入坐标不合法\n");
printf("玩家落子,請重新輸入x y坐标: ");
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;
}
如果對你有幫助和啟發,作者感到很高興。如果有好的建議,歡迎留言。如果發現錯誤,歡迎指正。新手上路,多多指點