功能说明:
黑棋与白棋进行博弈,先连满5个与自己颜色相同的棋子获胜。
函数要求:
1.棋子能够正常输入到棋盘中
2.能够正确判断棋子成功嬴棋:
(1)横向连满5个与自己颜色相同的棋子为获胜
(2)纵向连满5个与自己颜色相同的棋子为获胜
(3)正斜向连满5个与自己颜色相同的棋子为获胜
(4)负斜向连满5个与自己颜色相同的棋子为获胜
3.嬴棋了还可以再开一局
4.双方都输了(棋盘满了)可以再开一局
函数声明:
void initchessboard(PBoard pboard);//初始化
void start(PBoard pboarrd);//开始下棋
bool success(PBoard pboarrd, int cur_xpos, int cur_ypos, const char* chess_type);//判断赢局
//cur_xpos是x坐标,cur_ypos是y坐标, chess_type是当前棋子颜色
bool success_hx_position(PBoard pboarrd, int cur_xpos, int cur_ypos, const char* chess_type);//横向位置判断赢局
bool success_zx_position(PBoard pboarrd, int cur_xpos, int cur_ypos, const char* chess_type);//纵向位置判断赢局
bool success_zxx_position(PBoard pboarrd, int cur_xpos, int cur_ypos, const char* chess_type);//左斜向位置判断赢局
bool success_yxx_position(PBoard pboarrd, int cur_xpos, int cur_ypos, const char* chess_type);//右斜向位置判断赢局
bool isfull(PBoard pboard);//判断期盼是否为满
void show_board(PBoard pboard);//展示棋盘
写在前面:
一个汉字占2字节
英文+一个字节//这个就是普通字符
汉字+两个字节//键盘输“加”选择的加号
因为黑白棋符号的缘故,我们棋盘初始化界面的‘+’为汉字‘+’,这样在进行数组更换符号时才能一一对应上
//获取如下两个图标,键盘输入“圆圈”即可找到
⭕
●
//有的找的⭕找的是图标,也是1字节的,可以找个别的字符替代一下,比如□
所以下面的代码我就用□表示白棋,●表示黑棋
代码实现
chess.h
#pragma once
#include<stdio.h>
#define ROW 5//行
#define COLUMN 5//列
#define N 5//设置5个旗子连着为赢
typedef struct ChessBoard {
const char* chess_board[ROW][COLUMN];
int size;//记录当前棋盘有效棋子个数
}ChessBoard, * PBoard;
//功能函数
void initchessboard(PBoard pboard);//初始化
void start(PBoard pboarrd);//开始下棋
bool success(PBoard pboarrd, int cur_xpos, int cur_ypos, const char* chess_type);//判断赢局:横纵对角
//cur_xpos是x坐标,cur_ypos是y坐标, chess_type是当前棋子颜色
bool success_hx_position(PBoard pboarrd, int cur_xpos, int cur_ypos, const char* chess_type);//横向位置
bool success_zx_position(PBoard pboarrd, int cur_xpos, int cur_ypos, const char* chess_type);//纵向位置
bool success_zxx_position(PBoard pboarrd, int cur_xpos, int cur_ypos, const char* chess_type);//左斜向位置
bool success_yxx_position(PBoard pboarrd, int cur_xpos, int cur_ypos, const char* chess_type);//右斜向位置
bool isfull(PBoard pboard);//判断下满
void show_board(PBoard pboard);//展示棋盘
.cpp
//主程序
#include"chess.h"
int main()
{
ChessBoard chessboard;
start(&chessboard);
return 0;
}
.cpp
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<assert.h>
#include"chess.h"
#include<string.h>
void initchessboard(PBoard pboard)//初始化
{
pboard->size = 0;
for (int i = 0; i < ROW; i++)
{
for (int j = 0; j < COLUMN; j++)
{
pboard->chess_board[i][j] = { "+" };
}
}
}
bool success(PBoard pboarrd, int cur_xpos, int cur_ypos, const char* chess_type)//判断赢局:横纵对角
{
return(success_hx_position(pboarrd, cur_xpos, cur_ypos, chess_type)
|| success_zx_position(pboarrd, cur_xpos, cur_ypos, chess_type)
|| success_zxx_position(pboarrd, cur_xpos, cur_ypos, chess_type)
|| success_yxx_position(pboarrd, cur_xpos, cur_ypos, chess_type));
}
bool success_hx_position(PBoard pboarrd, int cur_xpos, int cur_ypos, const char* chess_type)//横向位置
{
//当前棋子的左边位置和右边位置遍历查找
int count = 0;//记录与当前棋子相同颜色的棋子个数
int i = cur_xpos;
for (int j = cur_ypos-1; j >= 0; j--)//左边
{
if (pboarrd->chess_board[i][j] == chess_type)
count++;
else
break;
}
//上面的for函数可以简化成
//for (int j = cur_ypos - 1&& pboarrd->chess_board[i][j] == chess_type; j >= 0; j--)//左边
//{
// count++;
//}
for (int j = cur_ypos ; j < COLUMN; j++)//右边
{
if (pboarrd->chess_board[i][j] == chess_type)
count++;
else
break;
}
if (count >= N)
{
printf("%s赢了!\n", chess_type);
return true;
}
else
return false;
}
bool success_zx_position(PBoard pboarrd, int cur_xpos, int cur_ypos,const char* chess_type)//纵向位置
{
//当前棋子的上边位置和下边位置遍历查找
int count = 0;//记录与当前棋子相同颜色的棋子个数
int j = cur_ypos;
for (int i = cur_xpos - 1; i >= 0; i--)//上边
{
if (pboarrd->chess_board[i][j] == chess_type)
count++;
else
break;
}
for (int i = cur_xpos; i < ROW; i++)//下边
{
if (pboarrd->chess_board[i][j] == chess_type)
count++;
else
break;
}
if (count >= N)
{
printf("%s赢了!\n", chess_type);
return true;
}
else
return false;
}
bool success_zxx_position(PBoard pboarrd, int cur_xpos, int cur_ypos, const char* chess_type)//左斜向位置
{
//当前棋子的左上位置和左下位置遍历查找
int count = 0;//记录与当前棋子相同颜色的棋子个数
int j = cur_ypos;
int i = cur_xpos;
//
for (; i >= 0 && j >=0 && pboarrd->chess_board[i][j] == chess_type; i--,j--)//左上
{ count++;
}
for (j = cur_ypos+1,i = cur_xpos+1; i <ROW && j <COLUMN && pboarrd->chess_board[i][j] == chess_type; i++, j++)//左下
{ count++;
}
if (count >= N)
{
printf("%s赢了!\n", chess_type);
return true;
}
else
return false;
}
bool success_yxx_position(PBoard pboarrd, int cur_xpos, int cur_ypos, const char* chess_type)//右斜向位置
{
//当前棋子的右上位置和右下位置遍历查找
int count = 0;//记录与当前棋子相同颜色的棋子个数
int j = cur_ypos;
int i = cur_xpos;
for (; i >=0 && j < COLUMN && pboarrd->chess_board[i][j] == chess_type; i--, j++)//右上
{
count++;
}
for (i = cur_xpos+1, j = cur_ypos -1; i < ROW && j >=0 && pboarrd->chess_board[i][j] == chess_type; i++, j--)//左下
{
count++;
}
if (count >= N)
{
printf("%s赢了!\n", chess_type);
return true;
}
else
return false;
}
void show_board(PBoard pboard)//展示棋盘
{
for (int i = 0; i < ROW; i++)
{
for (int j = 0; j < COLUMN; j++)
printf("%s",pboard->chess_board[i][j]);
printf("\n");
}
}
bool isfull(PBoard pboard)//判断满
{
return pboard->size == ROW * COLUMN ? true: false;
}
void start(PBoard pboard) //开始下棋
{
int choice;
const char* chess_type;
int xpos, ypos;
printf("五子棋游戏开始了!\n");
while(true){
initchessboard(pboard);//初始化棋盘
printf("请选择输入的棋子类型:\n1.白棋□,2.黑棋●,3.退出游戏\n");
scanf("%d", &choice);
if (choice == 3)
{
printf("游戏结束\n");
return;
}
//if(choice==1)
// chess_type = "□";
// else
// chess_type = "●";
chess_type = choice == 1 ? "□" : "●";
while (true)
{
show_board(pboard);
printf("请输入%s棋子的坐标(空格符间隔):\n", chess_type);
scanf("%d%d", &xpos, &ypos);
//对当前位置进行判断,若有棋子在就不能再下
//1.棋盘满 2,棋盘未满但该位置有棋子
//while (true)
{
if (pboard->chess_board[xpos][ypos] == "+")
{
pboard->chess_board[xpos][ypos] = chess_type;
pboard->size++;
//break;
}
else
{
//判满
if (isfull(pboard))
{
printf("棋盘已满\n是否需要重开一局,y or n?\n");
char num;
getchar();
scanf("%c", &num);
getchar();
//printf("%c", num);
if (num == 'y')
break;//跳出一层循环
else
{
printf("游戏结束\n");
return;
}
}
else
{
printf("该位置已有棋子,请重新输入:\n");
scanf("%d%d", &xpos, &ypos);
pboard->size++;
}
pboard->chess_board[xpos][ypos] = chess_type;
}
}
//判断该棋子是否为赢剧
if (success(pboard, xpos, ypos, chess_type))
{
show_board(pboard);
printf("%s棋子获胜\n是否需要重开一局,y or n?\n", chess_type);
char num;
getchar();
scanf("%c",&num);
getchar();
//printf("%c", num);
if (num == 'y')
break;//跳出一层循环
else
{
printf("游戏结束\n");
return;
}
}
else
chess_type = chess_type == "●"?"□":"●";
}
}
}
结果:
初始化界面调试:
检验已有棋子位置是否可以重复下棋:
检查横向位置成功情况:
检查纵向位置成功情况:
检查左斜向位置获胜情况:
检查右斜向位置获胜情况:
重开局测验:
判断棋盘为满:
代码解析:
除了在代码内部“//”出来的,还有一些需要解释的地方
1.键盘对于字符的获取:
本来scanf("%c",&num);就可以,但是在输入的时候缓冲区有\n输入只有也有\n的存在,会导致,实际输入的内容为:
\n
y
\n,因而对于num与'y'比较时也出错,因此用getchar();函数捕捉掉“\n”,即为如下代码所示。