Thread komischer fehler aber wo? (7 answers)
Opened by conray at 2010-04-22 21:31

MatthiasW
 2010-04-22 23:02
#136382 #136382
User since
2008-01-27
367 Artikel
BenutzerIn
[default_avatar]
Hm.. also erstmal würde ich sagen, der Spieler sollte sehen, welche Indizes zu den jeweiligen Zellen gehören. Außerdem wird das erste Element in einem Array per default mit 0 indiziert, aber das ist nur eine Kleinigkeit.

Ich finde ein paar Dinge sollten in eigene Funktionen gepackt werden, wie bspw. das Ausgeben des Spielfeldes oder das Überprüfen ob jemand gewonnen hat.

Damit nicht mehr so viele Variablen gebraucht und getauscht werden müssen, würde ich mir merken, wer gerade an der Reihe ist: 1 = Spieler 1, 0 = Spieler 2, oder umgekehrt. Der Spielstein und Spielername ergibt sich dann daraus.

Außerdem sollte ein getätigter Zug aus den möglichen gelöscht werden.

Ansonsten finde ich das system('clear') nicht so toll und würde stattdessen entweder je nach Betriebssystem etwas anderes tun, oder eine bestimmte Anzahl an Leerzeilen ausgeben (sollte für den Effekt genügen).

Hier ein alternativer Vorschlag:
Code (perl): (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#!/usr/bin/perl

use 5.010;
use strict;
use warnings;

# spielernamen:
print "Player 1: ";
chomp( my $player1 = <STDIN> );

$player1 =~ s/^\s*$/Player1/;

print "Player 2: ";
chomp( my $player2 = <STDIN> );

$player2 =~ s/^\s*$/Player2/;
$player2 .= '2' if $player2 eq $player1;

my @board;     # spielfeld
my $winner;    # gewinner
my $color = 1; # 1 = X, 0 = O

# hauptschleife:
while ( not defined $winner and scalar( grep defined, @board ) != 9 ) {
    draw_board();
    handle_input();
    check_winner();
} # while

# ausgabe des gewinners:
if ( defined $winner ) {
    draw_board();
    say "\nCongratulations ". ($winner eq 'X' ? $player1 : $player2) ."!";
    say "You are the winner!";
} # if
else {
    draw_board();
    say "\nDraw.";
} # else

# spielfeld zeichnen:
sub draw_board {
    print "\n" x 24; # bildschirm "loeschen" (edit)
    
    say "    A | B | C\n   -----------";
    printf(
        "%s:  %s | %s | %s\n". ($_ == 2 ? '' : "   ---+---+---\n"),
        $_ + 1,
        $board[3*$_  ] // ' ',#/
        $board[3*$_+1] // ' ',#/
        $board[3*$_+2] // ' ',#/
    ) for 0 .. 2;
} # draw_board

# eingabe entgegennehmen und behandeln:
sub handle_input {
    my( $name, $sym ) = $color ? ($player1, 'X') : ($player2, 'O');

    print "\nIt's your turn, $name ($sym): ";
    chomp( my $cell = <STDIN> );
    
    if ( $cell =~ /([abcABC])([123])/ ) {
        my( $x, $y ) = ( $1, $2 - 1 );
        $x = { 'a' => 0, 'b' => 1, 'c' => 2 }->{ lc $x };
        
        if ( defined $board[3*$y+$x] ) {
            say "This cell is already taken.";
            <STDIN>;
        } # if
        else {
            $board[3*$y+$x] = $sym;
            $color = !$color; # naechster spieler
        } # else
    } # if
    else {
        say "I'd appreciate something like A1 or b3.";
        <STDIN>;
    } # else
} # handle_input

# ueberpruefen ob jemand gewonnen hat:
sub check_winner {
    my $eq = sub { # edit: diese routine stände wohl besser in einem
        my $cmp = my $r = $board[shift]; # scope neben check_winner
        $r &&= $cmp eq $board[$_] for @_;
        return $r;
    }; # $eq

    # horizontal, vertikal, diagonal:
    for ( 0, 3, 6 ) { return $winner = $board[$_] if $eq->($_, $_+1, $_+2) }
    for ( 0, 1, 2 ) { return $winner = $board[$_] if $eq->($_, $_+3, $_+6) }
    $winner = $board[4] if $eq->(0, 4, 8) or $eq->(6, 4, 2);
} # check_winner

__END__

Last edited: 2010-04-22 23:44:41 +0200 (CEST)
perl -E'*==*",s;;%ENV=~m,..$,,$&+42;e,$==f;$"++for+ab..an;@"=qw,u t,,print+chr;sub f{split}say"@{=} me"'

View full thread komischer fehler aber wo?