@[TOC]
前言:
1.本文的三字琪,针对电脑是一种随机落子,不智能(后面会进行修改)。 |
2.因为在对胜负的判断很麻烦,因此我的思路:建立一个大原先棋盘2圈 的新 棋盘,(下棋范围仍是原棋盘,大2圈是为了边界情况的判定) 这样的话判断胜负时,我只需要判断落子后周围2圈 的情况 |
3.电脑下琪是随机下棋,因此需要随机数:见我了我一篇博客:伪随机数的生成 |
4.这需要很多的函数,为了mian函数文件的好看,自定义库函数,main.c文件调用相应函数 |
5.为了提高程序的灵活性,我把棋盘定义为全局变量,这样方便更改棋盘大小。 |
6.return可以直接结束函数运行,break只能结束一层循环,仔细体会其中妙处。后面的判断胜负函数就用到了,有兴趣的请看程序,非常的妙 。 |
7.在最终判断是无论胜负,平局都返回0,否则1.特别妙。0.0. |
|
我想要的棋盘
![image-20210817004108672 image-20210817004108672](https://ucc.alicdn.com/images/user-upload-01/img_convert/8ff51b5a8d15dd08a5b7805cbb461542.png?x-oss-process=image/resize,w_1400/format,webp)
思路:
程序代码(分步+汇总)
自定义函数库:game.h
#pragma once
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#define Row 9
#define Col 9
#define Rows Row+4
#define Cols Col+4
void Beg_board(char board[Rows][Cols] ,int row, int col);//初始化棋盘
void Show_board(char board[Rows][Cols], int row, int col);//用于输出棋盘
char Peo_ply(char board[Rows][Cols], int row, int col);//玩家走
char Com_ply(char board[Rows][Cols], int row, int col);//电脑走
char Is_win(char board[Rows][Cols], int x, int y, int row, int col);//返回判断的信息.
int Ret_win(char ch);//返回的值,用于终止游戏,
void game();//游戏执行
//玩家赢返回‘*’;
//电脑赢返回‘#’;
//平局返回'E';
//继续返回' C';
棋盘的初始化函数
void Beg_board(char board[Rows][Cols] ,int row, int col)
{
int i = 0;
int j = 0;
for(i=1;i<= row-3;i++)
{
for (j = 1; j <= col - 3 ; j++)
{
if (i==1)
{
board[i][j] = j - 1+'0';
board[j][i] = j - 1+'0';
}
else if(j>1)
{
board[i][j] = ' ';
}
}
}
}
输出棋盘函数
void Show_board(char board[Rows][Cols], int row, int col)
{
int i = 0;
int j = 0;
int t = 0;
for (i = 1; i < row - 2; i++)
{
for (j = 1; j < col - 2; j++)
{
if (i == 1)
{
printf(" %c ", board[i][j]);
}
else
{
if (j == 1)
{
printf(" %c |", board[i][j]);
}
else
{
printf(" %c |", board[i][j]);
}
}
}
printf("\n");
for (t = 0; t < col - 2; t++)
{
printf("----");
}
printf("\n");
}
}
玩家走函数
char Peo_ply(char board[Rows][Cols], int row, int col)
{
int x = 0;
int y = 0;
while (1)
{
printf("请输入坐标:");//字符数组的行列与坐标轴不同,但有规律
scanf("%d %d", &x, &y);
if (x > 0 && x < row - 3 && y>0 && y < col - 3)
{
if (board[y+1][x+1] == ' ')//防止重置电脑走的棋或者自己走过的棋
{
board[y+1][x+1] = '*';
Show_board(board, row, col);
break;
}
else
{
printf("坐标输入错误,请注意是否重复!\n");
}
}
else
{
printf("坐标输入错误,请注意横纵坐标轴!\n");
}
}
return Is_win(board, x, y, row, col);
}
判断胜负函数
周围2圈,共12种情况 |
判断胜负,只有连续3个不为空格,直接返回值。这地方非常妙 |
返回相应的字符,用以终止落子循环 |
char Is_win(char board[Rows][Cols], int x, int y, int row, int col)
{
int m = y + 1;//用于存储x,y的坐标.
int n = x + 1;
int i = 0;
int j = 0;
//判断周围一格的情况(直接返回字符,不需加以判断,但前提是非空格字符)
if ((board[m][n] == board[m][n - 1] )&& (board[m][n] == board[m][n + 1] )&& (board[m][n] != ' '))
{
return board[m][n];//比较左右
}
else if( (board[m][n] == board[m - 1][n] )&&( board[m ][n] ==board[m+1][n]) &&( board[m][n] != ' '))
{
return board[m][n];//比较上下
}
else if( (board[m][n] == board[m + 1][n + 1]) && (board[m][n] ==board[m - 1][n - 1] )&& (board[m][n] != ' '))
{
return board[m][n];//比较左上右下
}
else if ((board[m][n] == board[m - 1][n + 1] )&&( board[m][n] == board[m + 1][n - 1]) && (board[m][n] != ' '))
{
return board[m][n];//比较左下右上
}
//判断周围 2格的情况
else if ((board[m][n] == board[m][n - 1] )&& (board[m][n] == board[m][n - 2]) &&( board[m][n] != ' '))
{
return board[m][n];//比较左边2个
}
else if( (board[m][n] == board[m][n + 1] )&& (board[m][n] == board[m][n + 2] )&&( board[m][n] != ' '))
{
return board[m][n];//比较右边2个
}
else if ((board[m][n] == board[m - 1][n] )&& (board[m][n] == board[m - 2][n]) &&( board[m][n] != ' '))
{
return board[m][n];//比较上边2个
}
else if ((board[m][n] == board[m + 1][n] )&&( board[m][n] == board[m + 2][n] )&&( board[m][n] != ' '))
{
return board[m][n];//比较下边2个
}
else if ((board[m][n] == board[m + 1][n + 1] )&& (board[m][n] == board[m + 2][n + 2] )&& (board[m][n] != ' '))
{
return board[m][n];//比较右下2个
}
else if( (board[m][n] == board[m - 1][n + 1] )&&( board[m][n] == board[m - 2][n + 2]) && (board[m][n] != ' '))
{
return board[m][n];//比较右上2个
}
else if( (board[m][n] == board[m - 1][n - 1]) &&( board[m][n] == board[m - 2][n - 2]) && (board[m][n] != ' '))
{
return board[m][n];//比较左上2个
}
else if( (board[m][n] == board[m + 1][n - 1] )&&(board[m][n]== board[m + 2][n - 2])&&( board[m][n] != ' '))
{
return board[m][n];//比较左下2个
}
//判断是否继续:
for (i=2;i<row-3;i++)
for(j=2;j<col-3;j++)
if (board[i][j] == ' ')
return 'C';//碰到空格字符,程序结束。
//最后一种情况:平局,比较难判断,不过因为return的原因,变容易了。
return 'E';
}
电脑走(非智能电脑0.0)函数
char Com_ply(char board[Rows][Cols], int row, int col)
{
int x = 0;
int y = 0;
while (1)
{
x = rand() % (row - 3);
y = rand() % (col - 3);
if (x > 0 && x < row - 3 && y>0 && y < col - 3)
{
if (board[y+1][x+1] == ' ')//防止重置玩家,或者电脑走的位置。
{
board[y+1][x + 1] = '#';
Show_board(board, row, col);
break;
}
}
}
return Is_win(board, x, y, row, col);
}
终止落子函数
将判断胜负函数的返回值做为条件 |
无论谁赢,或者平局返回0,否则1 |
int Ret_win(char ch)//无论输赢,或者平局都返回0,继续则1;
{
if (ch == '*')
{
printf("恭喜你赢了!\n");
return 0;
}
else if (ch == '#')
{
printf("很遗憾,你输了!\n");
return 0;
}
else if (ch == 'E')
{
printf("本局平局!\n");
return 0;
}
else
{
return 1;
}
}
游戏执行函数
void game()
{
char game_board[Rows][Cols] = {0};
Beg_board(game_board, Rows, Cols);
Show_board(game_board, Rows, Cols);
while (1)
{
if(Ret_win(Peo_ply(game_board, Rows, Cols)))//玩家走,走完判断胜负情况
{
printf("继续游戏\n");
}
else
{
Show_board(game_board, Rows, Cols);
break;
}
if( Ret_win(Com_ply(game_board, Rows, Cols)))//玩家走,走完判断胜负情况
{
}
else
{
Show_board(game_board, Rows, Cols);
break;
}
}
}
汇总
//我的思路:
//在判断3三子棋情况,若是棋盘过大, 判断情况太多, 因此我设置了 - 个比原棋盘
//大2圈的棋盘,这样我只需在每次下棋后,判断周围2圈的情况,并返回值。再通
//过另外 - 个函数,将返回的值作为参数,只要不是继续的情况就返回0,否则就返
//回1.这样方便结束下棋的循环。
#include "game.h"
void menu()
{
printf("*********************************\n");
printf("****** 1.Play ***************\n");
printf("****** 0.Exit ***************\n");
printf("*********************************\n");
}
int main()
{
srand((unsigned int)time(NULL));
int input = 0;
do
{
menu();
printf("请输入:");
scanf("%d", &input);
switch (input)
{
case 1:game(); break;
case 0:printf("再见\n"); break;
default:printf("输入错误\n"); break;
}
} while (input);
return 0;
}
运行结果
![image-20210817002839571 image-20210817002839571](https://ucc.alicdn.com/images/user-upload-01/img_convert/4dd5882ef06033ee221756632b3eb2ef.png?x-oss-process=image/resize,w_1400/format,webp)
总结
1.return与break的灵活运用 |
2.多留意数组下标的位置。 |
3.注意x,y轴与二维数组行列的不同 |
4.五字棋等多子棋,和三字棋相似,但是需要确认周围几格内的元素,修改胜负判断条件即可。 |
|