大家好,又见面了,我是你们的朋友全栈君。
感知(SENSE)->
思考(THINK)->
行动(ACT)。所以,本文将尽量以这个顺序介绍实现过程。
#include<stdio.h>
#include<windows.h>
#define TRUE 1
#define FALSE 0
struct position {
int x;
int y;
int score;
};
char chess_board[16][16];
struct position positions[50];
int position_order;
void initialize_board(void)
{
int i, j;
for (i = 0;i < 16;i++) {
for (j = 0;j < 16;j++) {
chess_board[i][j] = ' ';
}
}
}
void initial_positions(void)
{
positions[0].x = positions[0].y = positions[0].score = 0;
for (position_order = 1;position_order < 50;position_order++) {
positions[position_order] = positions[0];
}
position_order = 0;
}
void print_board(void)
{
int i, j;
/*print letters*/
printf(" ");
for (j = 0;j < 16;j++) {
printf(" %c", 'A' + j);
}
putchar('\n');
/*print chess board*/
for (i = 0;i < 33;i++) {
if (i % 2 == 1) {
printf("%2d", (i + 1) / 2);
}
else {
printf(" ");
}
for (j = 0;j < 33;j++) {
/*The first row*/
if (i == 0 && j == 0) {
printf("┌ ");
}
else if (i == 0 && j==32) {
printf("┐");
}
else if (i == 0 && j % 2 == 0) {
printf("┬ ");
}
/*The last row*/
if (i == 32 && j == 0) {
printf("└ ");
}
else if (i == 32 && j == 32) {
printf("┘");
}
else if (i == 32 && j % 2 == 0) {
printf("┴ ");
}
/*The other rows*/
if (i != 0 && i != 32) {
if (i % 2 == 0) {
if (j == 0) {
printf("├ ");
}
else if (j == 32) {
printf("┤");
}
else if (j % 2 == 0) {
printf("┼ ");
}
}
else if(j % 2 == 0) {
printf(" %c", chess_board[(i - 1) / 2][(j + 1) / 2]);
}
}
}
putchar('\n');
}
}
int is_full(void) {
int i, j;
for (i = 0;i < 16;i++) {
for (j = 0;j < 16;j++) {
if (chess_board[i][j] == ' ')
return(FALSE);
}
}
return(TRUE);
}
void is_win(int x, int y, char cp)
{
int i, num=0;
/*row*/
for (i = 0;chess_board[y][x + i] == cp;i++, num++);
for (i = -1;chess_board[y][x + i] == cp;i--, num++);
if (num >= 5) {
system("cls");
print_board();
printf("%c win!", cp);
system("pause");
}
else {
num = 0;
}
for (i = 0;chess_board[y + i][x] == cp;i++, num++);
for (i = -1;chess_board[y + i][x] == cp;i--, num++);
if (num >= 5){
system("cls");
print_board();
printf("%c win!", cp);
system("pause");
}
else {
num = 0;
}
for (i = 0;chess_board[y + i][x + i] == cp;i++, num++);
for (i = -1;chess_board[y + i][x + i] == cp;i--, num++);
if (num >= 5) {
system("cls");
print_board();
printf("%c win!", cp);
system("pause");
}
else {
num = 0;
}
for (i = 0;chess_board[y + i][x - i] == cp;i++, num++);
for (i = -1;chess_board[y + i][x - i] == cp;i--, num++);
if (num >= 5) {
system("cls");
print_board();
printf("%c win!", cp);
system("pause");
}
else {
num = 0;
}
}
void scan(void)
{
char c;
int i;
do {
printf("输入落子行列:");
scanf_s("%d%c", &i, &c);
if (!(chess_board[i - 1][c - 'A'] == ' '))
continue;
chess_board[i - 1][c - 'A'] = '*';
break;
} while (TRUE);
is_win(c - 'A', i - 1, '*');
}
贴一张实际效果图:
(2)感知:
这一步中,将遍历棋盘中所有可落子位置,从横,纵,右斜和左斜四个方向,以棋子状态进行评分,总后将有效位置的总分记录在数组中。
下面先贴出的是评分函数,其接受一个大小为5的字符数组(记录在选定位置周围截取的包含该位置的”一行“棋子状态),一个描述选定位置在该行中的位置的参数x。内部由若干分支构成,对应每种棋子状态,返回对该状态的评分。
void reverse(char row[],int len) //由于一行棋子具有对称性,故x=3,x=4的状态可翻转归结为x=0,x=1的状态
{
char temp;
int i,j;
for (i = 0, j = len - 1;i <= j;i++, j--) {
temp = row[i];
row[i] = row[j];
row[j] = temp;
}
}
int score(char row[], int x) //'O'代表白棋,'*'代表黑棋,人执黑,机器执白
{ //每个if分支后的注释,'_'代表空格(即可落子处),'O'为白棋,'*'为黑棋
if (x > 2) { //'?'表示已可给分,该位置状态不必获取
reverse(row,5); //三者的排布代表截取行的棋子状态 x = 4 - x; //紧接着的return,返回的便是对该位置的评分
}
switch (x) {
case 0: {
if (row[1] == 'O' && (row[2] == 'O' || row[2] == ' ') && (row[3] == 'O' || row[3] == ' ') && (row[4] == 'O' || row[4] == ' ')) {
if (row[x + 2] == ' ') { //_O_??
return(15);
}
else if (row[x + 3] == ' ') { //_OO_?
return(50);
}
else if (row[x + 4] == ' ') { //_OOO_
return(90);
}
else { //_OOOO
return(1000);
}
}
else if (row[1] == '*' && (row[2] == '*' || row[2] == ' ') && (row[3] == '*' || row[3] == ' ') && (row[4] == '*' || row[4] == ' ')) {
if (row[x + 2] == ' ') { //_*_??
return(5);
}
else if (row[x + 3] == ' ') { //_**_?
return(30);
}
else if (row[x + 4] == ' ') { //_***_
return(70);
}
else { //_****
return(500);
}
}
};break;
case 1: {
if ((row[0] == 'O' || row[0] == ' ') && (row[2] == 'O' || row[2] == ' ') && (row[3] == 'O' || row[3] == ' ') && (row[4] == 'O' || row[4] == ' ')) {
if (row[0] == 'O') {
if (row[2] == ' ') { //O_ _??
return(15);
}
else if (row[3] == ' ') { //O_O_??
return(50);
}
else if (row[4] == ' ') { //O_OO_
return(90);
}
else { //O_OOO
return(1000);
}
}
else if (row[2] == ' ') { //_ _ _??
return(0);
}
else if (row[3] == ' ') { //_ _O_?
return(15);
}
else if (row[4] == ' ') { //_ _OO_
return(50);
}
else { //_ _OOO
return(80);
}
}
else if ((row[0] == '*' || row[0] == ' ') && (row[2] == '*' || row[2] == ' ') && (row[3] == '*' || row[3] == ' ') && (row[4] == '*' || row[4] == ' ')) {
if (row[0] == '*') {
if (row[2] == ' ') { //*_ _??
return(5);
}
else if (row[3] == ' ') { //*_*_?
return(30);
}
else if (row[4] == ' ') { //*_**_
return(70);
}
else { //*_***
return(500);
}
}
else if (row[2] == ' ') { //_ _ _??
return(0);
}
else if (row[3] == ' ') { //_ _*_?
return(5);
}
else if (row[4] == ' ') { //_ _**_
return(30);
}
else { //_ _***
return(60);
}
}
}break;
case 2: {
if ((row[0] == 'O' || row[0] == ' ') && (row[1] == 'O' || row[2] == ' ') && (row[3] == 'O' || row[3] == ' ') && (row[4] == 'O' || row[4] == ' ')) {
if (row[1] == 'O') {
if (row[3] == 'O') {
if (row[0] == 'O') {
if (row[4] == 'O') {//OO_OO
return(1000);
}
else {
return(90); //OO_O_
}
}
else {
if (row[4] == 'O') {//_O_OO
return(90);
}
else { //_O_O_
return(50);
}
}
}
else {
if (row[0] == 'O') { //OO_ _?
return(40);
}
else { //_O_ _?
return(15);
}
}
}
else {
if (row[3] == 'O') {
if (row[4] == 'O') { //_ _ _OO
return(40);
}
else { //_ _ _O_
return(15);
}
}
}
}
else if ((row[0] == '*' || row[0] == ' ') && (row[1] == '*' || row[2] == ' ') && (row[3] == '*' || row[3] == ' ') && (row[4] == '*' || row[4] == ' ')) {
if (row[1] == '*') {
if (row[3] == '*') {
if (row[0] == '*') {
if (row[4] == '*') {//**_**
return(500);
}
else { //**_*_
return(70);
}
}
else {
if (row[4] == '*') {//_*_**
return(70);
}
else { //_*_*_
return(30);
}
}
}
else {
if (row[0] == '*') { //**_ _ _
return(20);
}
else { //_*_ _?
return(5);
}
}
}
else {
if (row[3] == '*') { //_ _ _**
if (row[4] == '*') {
return(20);
}
else { //_ _ _*_
return(5);
}
}
}
}
}break;
}
return(0);
}
接下来呢,就是感知中的另一个主要部分,其功能是对某一位置,从四个方向,截取评分函数所需的一行五位置数组。
int sense_row(int x, int y) //横向截取,如下列一排示例中,x,y所代表的位置是第五个O{ //[OOOOO]OOOO,O[OOOOO]OOO,OO[OOOOO]OO......如此这般依次截取,其余方向类似 int sum = 0, i, j; char row[5]; for (i = x - 4;i <= x;i++) { if (!(i >= 0 && i + 4 <= 15)) { continue; } else { for (j = 0;j < 5;j++) { row[j] = chess_board[y][i + j]; } sum += score(row, x - i); } } return(sum);}int sense_col(int x, int y){ int sum = 0, i, j; char row[5]; for (i = y - 4;i <= y;i++) { if (!(i >= 0 && i + 4 <= 15)) { continue; } else { for (j = 0;j < 5;j++) { row[j] = chess_board[i + j][x]; } sum += score(row, y - i); } } return(sum);}int sense_right_bias(int x, int y){ int sum = 0, i, j; char row[5]; for (i = -4;i <= 0;i++) { if (!(y + i >= 0 && x + i >= 0 && y + i + 4 <= 15 && x + i + 4 <= 15)) { continue; } else { for (j = 0;j < 5;j++) { row[j] = chess_board[y + i + j][x + i + j]; } sum += score(row, -i); } } return(sum);}int sense_left_bias(int x, int y){ int sum = 0, i, j; char row[5]; for (i = -4;i <= 0;i++) { if (!(y - i <= 15 && x + i >= 0 && y - i - 4 >= 0 && x + i + 4 <= 15)) { continue; } else { for (j = 0;j < 5;j++) { row[j] = chess_board[y - i - j][x + i + j]; } sum += score(row, -i); } } return(sum);}void sense(void) //将四个方向上的评分综合并记录{ int x, y, sum = 0; initial_positions(); for (y = 0;y < 16;y++) { for (x = 0;x < 16;x++) { if (chess_board[y][x] != ' ') { continue; } sum += sense_col(x, y); sum += sense_row(x, y); sum += sense_left_bias(x, y); sum += sense_right_bias(x, y); if (sum != 0) { positions[position_order].score = sum; positions[position_order].x = x; positions[position_order].y = y; position_order++; sum = 0; } } }}
void think_act(void){ int max = 0, max_order, i; for (i = 0;i < position_order;i++) { if (positions[i].score > max) { max = positions[i].score; max_order = i; } } chess_board[positions[max_order].y][positions[max_order].x] = 'O'; is_win(positions[max_order].x, positions[max_order].y, 'O');}
void main(void){ initialize_board(); print_board(); while (!is_full()) { scan(); sense(); think_act(); system("CLS"); print_board(); } system("pause");}
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/148241.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...