7

騎士のすべての動きを生成する必要があるチェス プログラムを Python で作成しています。チェスに慣れていない人のために説明すると、ナイトは L 字型に動きます。

したがって、騎士の位置を考えると、 、、、 ) などに(2, 4)移動でき、合計 (最大) 8 つの異なる移動が可能です。(0, 3)(0, 5)(1, 2)(3, 2

knight_movesこれらのタプルをリストに生成するという関数を書きたいと思います。Pythonでこれを行う最も簡単な方法は何ですか?

def knight_moves(position):
    ''' Returns a list of new positions given a knight's current position. '''
    pass
4

9 に答える 9

9

わかりました、Niall Byrne のおかげで、私はこれを思いつきました:

from itertools import product
def knight_moves(position):
    x, y = position
    moves = list(product([x-1, x+1],[y-2, y+2])) + list(product([x-2,x+2],[y-1,y+1]))
    moves = [(x,y) for x,y in moves if x >= 0 and y >= 0 and x < 8 and y < 8]
    return moves
于 2013-10-15T03:13:22.130 に答える
8

移動できる相対ペアを保存しないのはなぜですか? したがって、開始点を取り、そこから離れた一連の可能な動きを追加すると、それらがまだ境界内にあるか、別の部分にないことを確認するために健全性チェックが必要になります.

つまり、(2, 4) 開始点が与えられた場合、オプションは (-2,-1)、(-2,+1)、(-1,+2)、(+2,+1) です。相対位置は次のようになります。常に同じであること。

于 2013-10-15T03:10:05.717 に答える
5

チェスに詳しくない...

deltas = [(-2, -1), (-2, +1), (+2, -1), (+2, +1), (-1, -2), (-1, +2), (+1, -2), (+1, +2)]
def knight_moves(position):
    valid_position = lambda (x, y): x >= 0 and y >= 0 and ???
    return filter(valid_position, map(lambda (x, y): (position[0] + x, position[1] + y), deltas))
于 2013-10-15T03:17:49.117 に答える
4

配列を使用する代わりに、ビットボードを使用することをお勧めします。それらは操作が非常に簡単であるだけでなく、境界チェックの必要性も減らします。わずか 12 個のビットボードで、ゲーム全体に必要な情報をエンコードできる可能性があります。

https://www.chessprogramming.org/Bitboards

ビットボードの基本的な考え方は、64 ビット整数を使用し、ビットにピースが存在する場合に 1 を設定することです。たとえば、白い騎士を表す 64 ビットの整数がある場合、ゲームの開始時に 2 番目と 6 番目のビットを設定します。これらは白い騎士が配置されている位置だからです。この表記法を使用すると、騎士の動きを簡単に計算できます。他の駒の動きも簡単に計算できます。

この表現を使用すると、騎士の動きを実装するための既製のアルゴリズムについて、チェス エンジンへのこのリンクを見ることができます。
http://www.mayoti.com/nagaskakichess6.html

于 2014-10-25T04:16:34.490 に答える
1

簡単な実装を次に示します。

def knights_moves():
  a = []
  b = (1, 2)
  while 1:
    a.append(b)
    b = (-b[0], b[1])
    a.append(b)
    b = (b[1], b[0])
    if b in a:
      return a

[(1, 2), (-1, 2), (2, -1), (-2, -1), (-1, -2), (1, -2), (-2, 1), (2, 1)]

そこから、このリストのすべてのメンバーに現在の位置を追加するだけで、有効性を再確認できます。

于 2013-11-29T21:54:41.137 に答える
1

xiaowlの答えを完成させて、

possible_places = [(-2, -1), (-2, +1), (+2, -1), (+2, +1), (-1, -2), (-1, +2), (+1, -2), (+1, +2)]
def knight_moves(cur_pos):
    onboard = lambda (x, y): x >= 0 and y >= 0 and x<8 and y<8
    eval_move = lambda(x,y): (cur_pos[0] + x, cur_pos[1] + y)
    return filter(onboard, map(eval_move, possible_places))
于 2014-01-09T06:22:32.480 に答える
0
from itertools import product

def moves():
    """ The available (relative) moves"""
    a = list(product( (1, -1), (2,-2)))
    return a + [tuple(reversed(m)) for m in a]

def neighbors(a,b):
    # true if x,y belongs in a chess table
    in_table = lambda (x, y): all((x < 8, y < 8, x >= 0, y >= 0))
    # returns the possible moving positions
    return filter(in_table, [(a+x, b+y) for x, y in moves()])

「隣人」は、騎士がa、bから移動できる利用可能な位置です

于 2016-01-07T19:06:19.713 に答える