独立钻石棋(Diamond Chess)算法

第一种方法,深度搜索的递归方法
/*
CODE BY 我的BLOG AT 2004.10.13
独立钻石棋问题
深度搜索,递归调用法
*/

#include<iostream>
#include<fstream>
using namespace std;

#define IN1// 有棋子
#define NOTIN0// 没有棋子
#define NEVERIN 2// 不可到达位置
#define MAXN7// 棋盘大小
#define STEP31// 31步结束

int c[MAXN+1][MAXN+1];// 存储空间
int pass[4][2]={{0,-1},{-1,0},{0,1},{1,0}};// 四个方向跳过位置
int reach[4][2]={{0,-2},{-2,0},{0,2},{2,0}};// 四个方向到达位置
bool findit = false;// 记录是否找到结果

// 输出一个棋局
void output(int c[][MAXN+1]);
// 递归搜索解
void Search(int depth);

int main(void)
{
ifstream cin("cin.txt");
// 输入
for(int i=1;i<=MAXN;i++){
for(int j=1;j<=MAXN;j++){
cin>>c[i][j];
}
}
// 处理
Search(0);
// 输出
system("pause");
return 0;
}

void Search(int depth)
{
if(depth == STEP && c[4][4] == 1){// 到达目标位置
cout<<"找到解,倒着走如下:\n";
output(c);
findit = true;
return;
}
int x1,y1,x2,y2;
for(int i=1;i<=MAXN;i++){
for(int j=1;j<=MAXN;j++){
if(c[i][j]==IN){// 有棋子
for(int k=0;k<4;k++){// 4个方向
x1 = i+pass[k][0];
y1 = j+pass[k][1];
x2 = i+reach[k][0];
y2 = j+reach[k][1];
if(x1>=1&&x1<=MAXN&&y1>=1&&y2<=MAXN&&c[x1][y1]==IN//跳过位置还有子
&&x2>=1&&x2<=MAXN&&y2>=1&&y2<=MAXN&&c[x2][y2]==NOTIN){//达到为位置为空
c[i][j]=NOTIN;// 初始位置置空
c[x1][y1]=NOTIN;// 跳过位置置空
c[x2][y2]=IN;// 跳到的位置置为peg
Search(depth+1);// 跳到目标位置
c[i][j]=IN;// 还原
c[x1][y1]=IN;
c[x2][y2]=NOTIN;

if(findit == true){
output(c);
return;
}
}
}
}
}
}
}

void output(int c[][MAXN+1])
{
cout<<"*********************************************************\n";
for(int i=1;i<=MAXN;i++){
for(int j=1;j<=MAXN;j++){
cout<<c[i][j]<<" ";
}
cout<<"\n";
}
}
第二种:常用方法深度搜索的open集和closed集算法,用堆是为了给启发式模板准备.
#ifndef NODE_H
#define NODE_H

#include <iostream>
using namespace std;

class Node {

friend ostream &operator <<(ostream &output,const Node & op2);// 输出当前布局

public:

int c[34];// 棋局状态
int moveid[32];// 各步移动的棋子号,第0个元素存放了到该棋局为止移动的步数
int dirction[32];// 各步的到达该局的移动方向,1,2,3,4分别为上下左右
int key;// 关键码,由于解空间不大,直接只用深度搜索

Node();

bool operator> (const Node &op2) const;// 建堆和向量需要重载的几个运算符
bool operator< (const Node &op2) const;
bool operator>=(const Node &op2) const;
bool operator==(const Node &op2) const;

void output(ostream &out) const;// 输出解

bool up(int id, Node& next);// 判断某一棋子的移动,移动后的布局存在next结点
bool down(int id, Node& next);
bool left(int id, Node& next);
bool right(int id, Node& next);

};

#endif

#include <iostream>
#include <fstream>
#include "Node.h"
using namespace std;

// 下移的位置
int downit[34][2] =
{{0,0},
{4,9},{5,10},{6,11},
{9,16},{10,17},{11,18},
{14,21},{15,22},{16,23},{17,24},{18,25},{19,26},{20,27},
{0,0},{0,0},{23,28},{24,29},{25,30},{0,0},{0,0},
{0,0},{0,0},{28,31},{29,32},{30,33},{0,0},{0,0},
{0,0},{0,0},{0,0},
{0,0},{0,0},{0,0}};

// 上移的位置
int upit[34][2] =
{{0,0},
{0,0},{0,0},{0,0},
{0,0},{0,0},{0,0},
{0,0},{0,0},{4,1},{5,2},{6,3},{0,0},{0,0},
{0,0},{0,0},{9,4},{10,5},{11,6},{0,0},{0,0},
{14,7},{15,8},{16,9},{17,10},{18,11},{19,12},{20,13},
{23,16},{24,17},{25,18},
{28,23},{29,24},{30,25}};

// 左移的位置
int leftit[34][2] =
{{0,0},
{0,0},{0,0},{2,1},
{0,0},{0,0},{5,4},
{0,0},{0,0},{8,7},{9,8},{10,9},{11,10},{12,11},
{0,0},{0,0},{15,14},{16,15},{17,16},{18,17},{19,18},
{0,0},{0,0},{22,21},{23,22},{24,23},{25,24},{26,25},
{0,0},{0,0},{29,28},
{0,0},{0,0},{32,31}};

// 右移的位置
int rightit[34][2] =
{{0,0},
{2,3},{0,0},{0,0},
{5,6},{0,0},{0,0},
{8,9},{9,10},{10,11},{11,12},{12,13},{0,0},{0,0},
{15,16},{16,17},{17,18},{18,19},{19,20},{0,0},{0,0},
{22,23},{23,24},{24,25},{25,26},{26,27},{0,0},{0,0},
{29,30},{0,0},{0,0},
{32,33},{0,0},{0,0}};

//down 1,up 2,left 3,right 4;
bool Node::down(int id,Node& next)
{
if(downit[id][0] == 0){// 由于移动后出界不能移
return false;
}else{
if(c[downit[id][0]] == 1 && c[downit[id][1]] == 0){
next = *this;// 拷贝当前
next.key ++;

// 移动后的棋局
next.c[id] = 0;
next.c[downit[id][0]] = 0;
next.c[downit[id][1]] = 1;

// 记录移动到达的步数
next.moveid[0] ++;
next.moveid[next.moveid[0]] = id ;
next.dirction[next.moveid[0]] = 1;

return true;
}else{// 由于移动后位置不允许不能移
return false;
}
}
}

bool Node::up(int id,Node& next)
{
if(upit[id][0] == 0){// 由于移动后出界不能移
return false;
}else{
if(c[upit[id][0]] == 1 && c[upit[id][1]] == 0){
next = *this;// 拷贝当前
next.key ++;

// 移动后的棋局
next.c[id] = 0;
next.c[upit[id][0]] = 0;
next.c[upit[id][1]] = 1;

// 记录移动到达的步数
next.moveid[0] ++;
next.moveid[next.moveid[0]] = id ;
next.dirction[next.moveid[0]] = 2;
return true;
}else{// 由于移动后位置不允许不能移
return false;
}
}
}

bool Node::left(int id,Node& next)
{
if(leftit[id][0] == 0){// 由于移动后出界不能移
return false;
}else{
if(c[leftit[id][0]] == 1 && c[leftit[id][1]] == 0){
next = *this;// 拷贝
next.key ++;

// 移动后的棋局
next.c[id] = 0;
next.c[leftit[id][0]] = 0;
next.c[leftit[id][1]] = 1;

// 记录移动到达的步数
next.moveid[0] ++;
next.moveid[next.moveid[0]] = id ;
next.dirction[next.moveid[0]] = 3;
return true;
}else{// 由于移动后位置不允许不能移
return false;
}
}
}

bool Node::right(int id,Node& next)
{
if(rightit[id][0] == 0){
return false;
}else{
if(c[rightit[id][0]] == 1 && c[rightit[id][1]] == 0){
next = *this;// 拷贝
next.key ++;

// 移动后的棋局
next.c[id] = 0;
next.c[rightit[id][0]] = 0;
next.c[rightit[id][1]] = 1;

// 记录移动到达的步数
next.moveid[0] ++;
next.moveid[next.moveid[0]] = id ;
next.dirction[next.moveid[0]] = 4;
return true;
}else{
return false;
}
}
}

Node::Node()
{
memset(c,0,sizeof(c));
moveid[0] = 0;
}

bool Node::operator> (const Node &op2) const
{
if(key>op2.key)
return
true;
else
return
false;
}
bool Node::operator< (const Node &op2) const
{
if(key<op2.key)
return
true;
else
return
false;
}
bool Node::operator>=(const Node &op2) const
{
if(key>=op2.key)
return
true ;
else
return
false;
}
bool Node::operator==(const Node &op2) const
{
for(int i=1;i<=33;i++){
if(c[i]!=op2.c[i])
return false;
}
return true;
}
void Node::output(ostream &out) const
{
out<<"\n--------------------------各步走法如下-------------------\n";
Node tmp = *this;
for(int i=1;i<=33;i++)
tmp.c[i] = 1;
tmp.c[17] = 0;
out<<tmp;
for(int i=1;i<=31;i++){
if(tmp.dirction[i] == 1){
tmp.c[tmp.moveid[i]] = 0;
tmp.c[downit[tmp.moveid[i]][0]] = 0;
tmp.c[downit[tmp.moveid[i]][1]] = 1;
out<<"移动棋子:"<<tmp.moveid[i]<<"号,移动方向:向下.\n";
}else if(tmp.dirction[i] == 2){
tmp.c[tmp.moveid[i]] = 0;
tmp.c[upit[tmp.moveid[i]][0]] = 0;
tmp.c[upit[tmp.moveid[i]][1]] = 1;
out<<"移动棋子:"<<tmp.moveid[i]<<"号,移动方向:向上.\n";
}else if(tmp.dirction[i] == 3){
tmp.c[tmp.moveid[i]] = 0;
tmp.c[leftit[tmp.moveid[i]][0]] = 0;
tmp.c[leftit[tmp.moveid[i]][1]] = 1;
out<<"移动棋子:"<<tmp.moveid[i]<<"号,移动方向:向左.\n";
}else if(tmp.dirction[i] == 4){
tmp.c[tmp.moveid[i]] = 0;
tmp.c[rightit[tmp.moveid[i]][0]] = 0;
tmp.c[rightit[tmp.moveid[i]][1]] = 1;
out<<"移动棋子:"<<tmp.moveid[i]<<"号,移动方向:向右.\n";
}
out<<tmp;
}
out<<"\n----------------------移动完成-----------------------\n";
}

ostream &operator <<(ostream &output,const Node &op2)
{
output<<" "<<op2.c[1]<<" "<<op2.c[2]<<" "<<op2.c[3]<<" \n";
output<<" "<<op2.c[4]<<" "<<op2.c[5]<<" "<<op2.c[6]<<" \n";
for(int i=1;i<=3;i++){
for(int j=7*i;j<7*(i+1);j++){
output<<op2.c[j]<<" ";
}
output<<"\n";
}
output<<" "<<op2.c[28]<<" "<<op2.c[29]<<" "<<op2.c[30]<<" \n";
output<<" "<<op2.c[31]<<" "<<op2.c[32]<<" "<<op2.c[33]<<" \n";
return output;
}
/*
CODY BY 01120136 我的BLOG AT 2004.10.9
独立钻石棋问题, 深度优先搜索,尽量清除重复点
棋盘编号布局如下:
01 02 03
04 05 06
07 08 09 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
31 32 33
*/

#include <iostream>
#include <fstream>
#include <algorithm>
#include <vector>
#include "Node.h"
using namespace std;

vector<Node> open;// OPEN集
vector<Node> closed;// CLOSED集
vector<Node>::iterator iter;

// 判断next结点是否已扩展过,是返回true,否则false
bool extended(Node &next);
// 搜索解
void search();

int main(void)
{

search();
system("pause");
return 0;
}

void search()
{
// 初始化
Node first;
for(int i=1;i<=33;i++){
first.c[i] = 1;
}
first.c[17] = 0;
first.key = 0;
open.push_back(first);

// 开始循环
while(!open.empty()){
cout<<"正在搜索...... 已扩展结点:"<<closed.size()<<"\n";
make_heap(open.begin(),open.end());// 建最大堆
pop_heap(open.begin(),open.end());// 取走堆首元素,可为启发式搜索准备
Node tmp = open.back();
open.pop_back();

// 看所取节点是否为目标节点
if(tmp.moveid[0] >= 31 && tmp.c[17] == 1){
tmp.output(cout);// 输出解并返回
ofstream out("out.txt");
tmp.output(out);
return ;
}

// 若不是则生成所有的子状态
Node next;
bool hadit;
for(int i = 1;i <= 33 ;i++){
if(tmp.c[i] != 0){
if( tmp.down(i,next)){
if(extended(next) == false){// 还没扩展过
open.push_back(next);
}
}
if( tmp.up(i,next)){
if(extended(next) == false){// 还没扩展过
open.push_back(next);
}
}
if( tmp.left(i,next)){
if(extended(next) == false){// 还没扩展过
open.push_back(next);
}
}
if( tmp.right(i,next)){
if(extended(next) == false){// 还没扩展过
open.push_back(next);
}
}
}
}
// 将刚才取出的open点放入closed表
closed.push_back(tmp);
}
}

bool extended(Node &next)
{
// 若next在closed中,即已扩展过了,返回true
for(iter = closed.begin();iter !=closed.end();iter++){
if(*iter == next){
return true;
}
}
// 若已在open集中,则返回true;
for(iter = open.begin();iter !=open.end();iter++){
if(*iter == next){
return true;
}
}
// 都没有则返回false
return false;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的五子人机算法的 Python 代码示例: ```python import random SIZE = 15 # 盘大小 CHESS_EMPTY = 0 CHESS_PLAYER = 1 CHESS_COMPUTER = 2 WIN = 1 LOSE = -1 DRAW = 0 # 初始化盘 def init_board(): board = [] for i in range(SIZE): row = [CHESS_EMPTY] * SIZE board.append(row) return board # 人机对弈 def play(): board = init_board() print_board(board) while True: player_move(board) winner = check_winner(board) if winner != CHESS_EMPTY: break computer_move(board) winner = check_winner(board) if winner != CHESS_EMPTY: break print_board(board) if winner == CHESS_PLAYER: print("你赢了!") elif winner == CHESS_COMPUTER: print("电脑赢了!") else: print("平局!") # 人类下 def player_move(board): while True: x, y = map(int, input("请输入你的坐标(x,y): ").split(',')) if board[x][y] == CHESS_EMPTY: board[x][y] = CHESS_PLAYER break else: print("该位置已经有子了,请重新输入!") # 电脑下 def computer_move(board): x, y = find_best_move(board) board[x][y] = CHESS_COMPUTER print("电脑落子坐标为:({},{})".format(x, y)) # 查找最佳落子位置 def find_best_move(board): best_score = -1000 best_move = (0, 0) for i in range(SIZE): for j in range(SIZE): if board[i][j] == CHESS_EMPTY: score = evaluate_move(board, i, j) if score > best_score: best_score = score best_move = (i, j) return best_move # 评估落子位置得分 def evaluate_move(board, x, y): score = 0 score += evaluate_line(board, x, y, 0, 1) # 水平方向得分 score += evaluate_line(board, x, y, 1, 0) # 垂直方向得分 score += evaluate_line(board, x, y, 1, 1) # 正斜方向得分 score += evaluate_line(board, x, y, -1, 1) # 反斜方向得分 return score # 评估一条线上的得分 def evaluate_line(board, x, y, dx, dy): player_count = 0 # 玩家子数量 computer_count = 0 # 电脑子数量 empty_count = 0 # 空位数量 line_score = 0 # 该线得分 for i in range(5): xi = x + i * dx yi = y + i * dy if xi < 0 or xi >= SIZE or yi < 0 or yi >= SIZE: break if board[xi][yi] == CHESS_PLAYER: player_count += 1 elif board[xi][yi] == CHESS_COMPUTER: computer_count += 1 else: empty_count += 1 if player_count == 4: # 玩家连四 line_score = LOSE elif computer_count == 4: # 电脑连四 line_score = WIN elif computer_count == 3 and empty_count == 1: # 活三 line_score = 100 elif player_count == 3 and empty_count == 1: # 防守活三 line_score = 90 elif computer_count == 2 and empty_count == 2: # 活二 line_score = 50 elif player_count == 2 and empty_count == 2: # 防守活二 line_score = 40 return line_score # 检查是否有胜者 def check_winner(board): # 检查行 for i in range(SIZE): for j in range(SIZE - 4): if board[i][j] == board[i][j+1] == board[i][j+2] == board[i][j+3] == board[i][j+4] and board[i][j] != CHESS_EMPTY: return board[i][j] # 检查列 for i in range(SIZE - 4): for j in range(SIZE): if board[i][j] == board[i+1][j] == board[i+2][j] == board[i+3][j] == board[i+4][j] and board[i][j] != CHESS_EMPTY: return board[i][j] # 检查正斜线 for i in range(SIZE - 4): for j in range(SIZE - 4): if board[i][j] == board[i+1][j+1] == board[i+2][j+2] == board[i+3][j+3] == board[i+4][j+4] and board[i][j] != CHESS_EMPTY: return board[i][j] # 检查反斜线 for i in range(SIZE - 4): for j in range(4, SIZE): if board[i][j] == board[i+1][j-1] == board[i+2][j-2] == board[i+3][j-3] == board[i+4][j-4] and board[i][j] != CHESS_EMPTY: return board[i][j] # 没有胜者 if CHESS_EMPTY in (x for row in board for x in row): return CHESS_EMPTY else: return DRAW # 打印盘 def print_board(board): print(" ", end="") for i in range(SIZE): print("{:2d}".format(i), end="") print() for i in range(SIZE): print("{:2d} ".format(i), end="") for j in range(SIZE): if board[i][j] == CHESS_EMPTY: print(". ", end="") elif board[i][j] == CHESS_PLAYER: print("X ", end="") else: print("O ", end="") print() if __name__ == '__main__': play() ``` 该代码实现了一个比较简单的五子人机对弈算法,使用了基于评估函数的博弈树搜索方法,其中评估函数主要考虑了子连成的线型、数量和空位等因素,从而评估每个落子位置的得分,并选择最高得分的位置作为电脑的落子位置。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值