简介
这个任意子棋向玩家提供任选棋盘大小、任选连珠数量功能。但缺点是电脑太傻只会随机落子、不能用鼠标点击、没有可视化的图形界面。这里的电脑下棋我使用的是随机函数,所以与玩家对战的电脑显得很智障。其实这也是类似于五子棋这一类棋牌游戏的难点所在。想要使电脑聪明,完全可以–人工智能啊深度学习啊什么的,但是明显我不会。在这里我想到了两种使电脑看起来“聪明”的办法,第一种:加上各种if语句来模拟各种情景下电脑应该怎样走–这种方法不是一个聪明的计算机本科生应该做的,pass; 第二种:写一个算法,判断图的连通性,根据图的连通性再权衡进攻或者防守,动态地做出判断–明显这种方法特别复杂,等到以后再写吧。
我所使用的是VS2008, 采用TDD模式,任意子棋程序分为3个源文件,分别是:game.h 、game.c 、index.c
源代码
game.h 文件中放声明, game.c 里放函数的定义, index.c 里放主函数。
index.c
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include "game.h"
int x=0, y=0;
int main(){
int level=0, num=0, Pioneer=0;
char sign='\0';
char board[ROW][COL];
int again=0;
int c=0;
srand((unsigned int)time(NULL));
AGAIN1: Creat_Rule(&level, &num, &Pioneer);
AGAIN2: Init_Board(board,level);
Show_Board(board,level);
if(Pioneer==1) //玩家先走
{
while(1)
{
Player_Do(board,level);
Show_Board(board,level);
sign=Judge_Win(board,level, num);
// printf("sign=%c\n",sign);
if(sign=='X')
{
printf("恭喜你,获胜!!!\n");
break;
}
else if(sign=='q')
{
printf("平局!\n");
break;
}
Computer_Do(board,level);
Show_Board(board,level);
sign=Judge_Win(board,level, num);
if(sign=='O')
{
printf("很遗憾,电脑胜!!!\n");
break;
}
else if(sign=='q')
{
printf("平局!\n");
break;
}
}
}
else //电脑先走
{
while(1)
{
Computer_Do(board,level);
Show_Board(board,level);
sign=Judge_Win(board,level, num);
// printf("sign=%c\n",sign);
if(sign=='O')
{
printf("恭喜你,获胜!!!\n");
break;
}
else if(sign=='q')
{
printf("平局!\n");
break;
}
Player_Do(board,level);
Show_Board(board,level);
sign=Judge_Win(board,level, num);
if(sign=='X')
{
printf("很遗憾,电脑胜!!!\n");
break;
}
else if(sign=='q')
{
printf("平局!\n");
break;
}
}
}
printf("********************************游戏结束****************************************\n");
printf("*****不玩了:0********重新开始:1********以当前规则再玩一局:2***************\n");
scanf("%d", &again);
while((c = getchar()) != '\n' && c != EOF);
// if(again!=0) (again==1) ? ( goto AGAIN1) : (goto AGAIN2);
switch (again)
{
case 1: goto AGAIN1; break;
case 2: goto AGAIN2; break;
default: return 0;
}
return 0;
}
game.h
#ifndef __GAME_H__
#define __GAME_H__
#include<stdio.h>
#include <string.h>
#include <stdlib.h>
#include<time.h>
#define ROW 36
#define COL 36
extern int x, y;
void Creat_Rule(int *level, int *num, int *Pioneer);
void Init_Board(char board[ROW][COL], int level);
void Show_Board(char board[ROW][COL], int level);
void Player_Do(char board[ROW][COL], int level);
void Computer_Do(char board[ROW][COL], int level);
char Judge_Win(char board[ROW][COL], int level, int num);
#endif
game.c
#define _CRT_SECURE_NO_WARNINGS
#include "game.h"
extern int x, y;
void Creat_Rule(int *level, int *num, int *Pioneer){
int c=0;
char affirm[5]={'\0'};
Loop:
printf("请选择棋盘大小(3阶到36阶)>");
while(scanf("%d", level))
{
int c=0;
while((c = getchar()) != '\n' && c != EOF); //清除键盘缓冲区的万能写法
if(*level<3) printf("输入错误,请重新指定\n");
else
{
break;
}
}
printf("您想玩几子连珠?(不得小于3)>");
while(scanf("%d", num))
{
int c=0;
while((c = getchar()) != '\n' && c != EOF); //清除键盘缓冲区的万能写法
if(*num<3) printf("输入错误,请重新输入\n");
else if(*num>*level)
{
printf("超过了棋盘的范围,请重新输入\n");
}
else
{
break;
}
}
printf("您和电脑谁先走?(若你先走,输入1;若电脑先走,输入2)>");
while(scanf("%d", Pioneer))
{
int c=0;
while((c = getchar()) != '\n' && c != EOF); //清除键盘缓冲区的万能写法
if(*Pioneer!=1 && *Pioneer!=2) printf("输入错误,请重新输入\n");
else
{
break;
}
}
printf("请确认规则:\n");
if(*Pioneer==1) printf("您定制的规则为: 在一个%d*%d的棋盘上,谁先将%d颗棋子连成一条线谁就赢了,您先走\n", *level, *level, *num);
else printf("您定制的规则为: 在一个%d*%d的棋盘上,谁先将%d颗棋子连成一条线谁就赢了,电脑先走\n", *level, *level, *num);
printf("****************确认并开始游戏?(Y/N)>");
scanf("%s", affirm);
while((c = getchar()) != '\n' && c != EOF); //清除键盘缓冲区的万能写法
if( !(strcmp(affirm, "Y")==0 || strcmp(affirm, "y")==0 || strcmp(affirm, "YES")==0 || strcmp(affirm, "yes")==0 || strcmp(affirm, "Yes")==0 ) ) goto Loop;
}
void Init_Board(char board[ROW][COL], int level){
int i=0, j=0;
/*board=(char **)malloc(sizeof(char *)*level);
for (i=0; i<level; i++)
{
board[i]=(char *)malloc(sizeof(char *)*level);
}*/
for(i=0; i<level; i++)
{
for(j=0; j<level; j++)
{
board[i][j]=' ';
}
}
}
void Show_Board(char board[ROW][COL], int level){
int i = 0, j = 0;
for(i=0; i<level; i++)
{
for(j=0; j<level; j++)
{
printf(" ---");
}
printf("\n");
for (j=0; j<level; j++)
{
printf("| %c ",board[i][j]);
}
printf("|\n");
if(i==level-1)
{
for(j=0; j<level; j++)
{
printf(" ---");
}
}
}
printf("\n");
}
int Judge_Legal(char board[ROW][COL], int level, int x, int y){
if(x>=level || y>=level || x<0 || y<0) return 1;
if(board[x][y]!=' ') return 2;
return 0;
}
void Player_Do(char board[ROW][COL], int level){
int c=0;
int a=0, b=0;
printf("Tips: 左上角为(1,1),右下角为(%d,%d)\n", level, level);
printf("玩家走>");
while(scanf("%d%d", &a,&b))
{
int c=0;
while((c = getchar()) != '\n' && c != EOF); //清除键盘缓冲区的万能写法
x=a-1;
y=b-1;
if(Judge_Legal(board, level, x, y)==0)
{
board[x][y]='X';
break;
}
else if(Judge_Legal(board, level, x, y)==1)
{
printf("您输入的位置不合法,请重新输入>");
}
else printf("这里已经有棋子了,请重新输入>");
}
}
void Computer_Do(char board[ROW][COL], int level){
printf("电脑走\n");
while(1)
{
x=rand()/level;
y=rand()/level;
if(Judge_Legal(board, level, x, y)==0)
{
board[x][y]='O';
break;
}
}
}
char Judge_Win(char board[ROW][COL], int level, int num){
int px=0, py=0;
int count=0;
char c=board[x][y];
//printf("x=%d, y=%d \n ", x, y);
//printf("c=%c\n",c);
if (c=='X' || c=='O')
{
count=0;
px=x;
py=0;
while(px>=0 && px<level && py>=0 && py<level) //一横排
{
(board[px][py]==c) ? (count ++) : (count=0);
if(count>=num) return c;
py++;
}
count=0;
py=y;
px=0;
while(px>=0 && px<level && py>=0 && py<level) //一列排
{
(board[px][py]==c) ? (count ++) : (count=0);
if(count>=num) return c;
px++;
}
if(x<y) //从左上角到右下角
{
px=0;
py=(y-x);
}
else
{
px=(x-y);
py=0;
}
count=0;
while(px>=0 && px<level && py>=0 && py<level)
{
(board[px][py]==c) ? (count ++) : (count=0);
if(count>=num) return c;
px++;
py++;
}
if( (level-(x+1))>y ) //从左下角到右上角
{
px=x+y;
py=0;
}
else
{
px=level-1;
py=y-(level-(x+1));
}
count=0;
while(px>=0 && px<level && py>=0 && py<level)
{
(board[px][py]==c) ? (count ++) : (count=0);
if(count>=num) return c;
px--;
py++;
}
}
for(px=0; px<level; px++)
{
for(py=0; py<level; py++)
{
if(board[px][py]==' ') goto Loop1;
}
}
return 'q';
Loop1:
return 'k';
}