Minesweeper

CDW

0
Mitarbeiter
eingereicht von Stein:
Es soll eine Minesweeper version programmiert werden, wobei eine textbasierende version schon vollkommen ausreichend ist.
http://de.wikipedia.org/wiki/Minesweeper

Code:
   3 - - - - - - -   
   - - - - - - - -   
   - - - - - - - -   
   - - - 5 - - - -   
   - - - - - - - -   
   - - - - - - - -   
   - - - - - - - -   
   - - - - - - - 1
 
Hier meine Variante in Python. Leider hab ich viel Zeit beim debuggen verloren
Code:
#Minefinder v0.2 is a textbased game. The user's task is to find tne hidden mines

#Copyright (C) 2008 Matthias Redies

#This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
#This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#You should have received a copy of the GNU General Public License along with this program; if not, see <http://www.gnu.org/licenses/>.

import random
import time
#eine Miene setzen
def setmine():
  x = random.randrange(0, groesse, 1)
  y = random.randrange(0, groesse, 1)
  if minen[x][y] == 1:
    setmine()
  else:
    minen[x][y]= 1


#Die unzensierte Ausgabe - nur zur Entwickelung
def ausgabeuz():
  for a in range(10):
    ausgabe = ""
    for b in range(10):
      if minen[b][a]== 1:
        ausgabe += "X "
      else:
        ausgabe += "O "
    print ausgabe


#Die zensierte Ausgabe      
def ausgabez():
  for a in range(groesse):
    ausgabe = ""
    for b in range(groesse):
      ausgabe = ausgabe + str(geklickt[b][a]) + " "
    print ausgabe

#Prueft ob alle Mienen gefunden wurden
def fertig():
  n = 0
  for a in range(groesse):
    for b in range(groesse):
      if geklickt[b][a] == "N":
        n += 1
  if n > m:
    return 0
  else:
    return 1

  
#"Klickruntiene"
def klick(x, y):
  if minen[x][y] == 1:
    print "Mine! Verloren"
    exit()
  else:
    geklickt[x][y] = umgebminen(x,y)


#loest rekursiv alle umliegenden Felder
def solvumgebung(x,y):
  #OL
  if (x-1 >= 0) and (y-1 >=0):
    geklickt[x-1][y-1]= umgebminen(x-1,y-1)
  #OM
  if (y-1 >= 0):
    geklickt[x][y-1]= umgebminen(x,y-1)
  #OR
  if (x + 1 <= groesse - 1) and (y-1 >= 0):
    geklickt[x+1][y-1]= umgebminen(x+1,y-1)
  #MR
  if(x+1 <= groesse - 1):
    geklickt[x+1][y]= umgebminen(x+1,y)
  #UR
  if (x+1 <= groesse - 1) and (y+1 <= groesse - 1):
    geklickt[x+1][y+1]= umgebminen(x+1,y+1)
  #UM
  if (y+1 <= groesse - 1):
    geklickt[x][y+1]= umgebminen(x,y+1)
  #UL
  if (x-1 >=0) and (y+1 <= groesse - 1):
    geklickt[x-1][y+1]= umgebminen(x-1,y+1)
  #ML
  if (x-1 <= 0):
    geklickt[x-1][y]= umgebminen(x-1,y)
  
  
#Zaehlt Mienen in der Umgebung
def umgebminen(x,y):
  ergebniss = 0
  #obenlinks
  if (x > 0) and (y > 0):
    if minen[x-1][y-1] == 1:
      ergebniss += 1
  #obenmitte
  if y > 0 :
    if minen[x][y-1] == 1:
      ergebniss += 1
  #obenrechts
  if (x < groesse - 1) and (y > 0):
    if minen[x+1][y-1] == 1:
      ergebniss += 1
  #mitterechts
  if x < groesse - 1:
    if minen[x+1][y] == 1:
      ergebniss += 1
  #untenrechts
  if (x < groesse - 1) and (y < groesse - 1):
    if minen[x+1][y+1]== 1:
      ergebniss += 1
  #untenmitte
  if y < groesse - 1:
    if minen[x][y+1]:
      ergebniss += 1
  #untenlinks
  if (x > 0) and (y < groesse - 1):
    if minen[x-1][y+1]==1:
      ergebniss += 1
  #mittelinks
  if x > 0:
    if minen[x-1][y]==1:
      ergebniss += 1

  
  if (ergebniss == 0) and (bearbeitet[x][y] == 0):
    bearbeitet[x][y] = 1
    solvumgebung(x,y)

  
  return ergebniss
    

minen = []
geklickt = []
bearbeitet = []
groesse = int(raw_input("Wie gross soll das Spielfeld sein?"))
#Spielfeld erstellen und alle Felder mit 0 => keinen Miene versehen
for i in range(groesse):
  bearbeitet.append([])
  minen.append([])
  geklickt.append([])
  for j in range(groesse):
    bearbeitet[i].append(0)
    minen[i].append(0)
    geklickt[i].append("N")

#Mienen auslosen
m = int(raw_input("Wie viele Minen sollen es sein?"))
for k in range(m):
  setmine()
ausgabez()

start = time.localtime()
while fertig() == 0:
  x = 11
  y = 11
  while (x < 0) or (x > 10):
    x = int(raw_input("Geben Sie X ein:"))
  while (y < 0) or (y > 10):
    y = int(raw_input("Geben Sie Y ein:"))
  klick(x-1,y-1)
  ausgabez()
ende = time.localtime()

print 'Fertig! Du hast '+ str(ende[4] - start[4]) + ' min. ' + str(ende[5]-start[5]) + ' sek. gebraucht!'
 
Meine Lösung in ABAP, allerdings schon relativ alt ;)
Code:
*&---------------------------------------------------------------------*
*& Report  ZMINE
*&
*&---------------------------------------------------------------------*
*& Das Spiel Minesweeper in SAP - ABAP realisieren.
*& Allerdings ohne Zeitabfrage, weil die sehr vom Server und dessen Last abhängt
*& Daher kann eine objektive Zeitmessung nicht erfolgen
*& COPYRIGHT Markus Völker - [email]mgv@gmx.de[/email]
*&---------------------------------------------------------------------*

REPORT zmine.

*Anlegen der Variablen für das Minenfeld und den Zugriff darauf (Workarray)
*sowie des eigentlichen Spielfeldes

*******
TYPES:
*******
        BEGIN OF tt_minefield,
           1 TYPE c,
           2 TYPE c,
           3 TYPE c,
           4 TYPE c,
           5 TYPE c,
           6 TYPE c,
           7 TYPE c,
           8 TYPE c,
           9 TYPE c,
        END OF tt_minefield.

*******
TYPES: tt_minefield_ty TYPE STANDARD TABLE OF tt_minefield
*******
                            WITH NON-UNIQUE DEFAULT KEY.

******
DATA:
******
      it_minefield TYPE tt_minefield_ty ,            "das Minenfeld
      wa_minefield TYPE LINE OF tt_minefield_ty,     "der Zugriff darauf
      blinder TYPE tt_minefield_ty,                  "verdeckt das Minenfeld
      wa_blinder TYPE LINE OF tt_minefield_ty,       "und zugriff
      result TYPE string,                            "ergebnisfeld der Blindtabelle zum löschen der Leerzeichen
      zeile TYPE i,                                  "angabe der aktuell zu durchlaufenden Zeile
      spalte TYPE i,                                 "angabe der aktuell zu durchlauifenden spalte
      counter TYPE i,                                "Hilfs-zähl-variable
      x TYPE i,                                      "x-Achse
      tempx type i,                                  "Variable um die WErte x -1 und x+1 aufzunehmen
      y TYPE i,                                      "y-Achse
      z Type i,                                      "temporäre Variable zur definition des Minenfeldes
      substance TYPE c,                              "Inhalt des Angeklickten Feldes
      temp_substance TYPE c                          "Übergabe des gefundenen Inhalts
      .

***************
FIELD-SYMBOLS:
***************
               <mine_line> TYPE LINE OF tt_minefield_ty,    "Linie eines Minenfeldes
               <blinder_line> TYPE LINE OF tt_minefield_ty, "Linie der blindertabelle
               <blinder_content> TYPE c,                    "Inhalt einer Zelle der Blindertabelle
               <content> TYPE c                             "inhalt der Spalten einer Zeile
               .

***************************
*     Funktionen          *
***************************
 include z_mine_functions. "Funktionen zum setzen, finden und holen von Werten aus ITs
***************************

*****************
INITIALIZATION.
*****************

*Belege das Minenfeld mit Minen

  include z_build_minefield.

*Belege Minenfeld mit Zahlen um die Minen

  include z_minefield.

*Belege das Blind-Feld mit #

PERFORM fill_table USING '#'
                   CHANGING blinder.

*  LOOP AT blinder ASSIGNING <blinder_line>.
*    DO.
*      ASSIGN COMPONENT sy-index OF STRUCTURE <blinder_line> TO <blinder_content>.
*      IF sy-subrc <> 0. EXIT. ENDIF.
*      <blinder_content> = '#'.
*    ENDDO.
*  ENDLOOP.

**********************
START-OF-SELECTION.
**********************


*erste AUSGABE des Blindfeldes

  LOOP AT blinder ASSIGNING <blinder_line>.
    CONCATENATE
              <blinder_line>-1 <blinder_line>-2 <blinder_line>-3
              <blinder_line>-4 <blinder_line>-5 <blinder_line>-6
              <blinder_line>-7 <blinder_line>-8 <blinder_line>-9
              INTO result.
    WRITE: / result.
  ENDLOOP.

***************************************************************************************************
* Bei jeder Feldauswahl wird in at line-selection der aktuelle X und Y Wert des Cursors abgefragt *
***************************************************************************************************

AT LINE-SELECTION.
* sollte der Anwender die F3 Taste benutzt haben und erneut aussuchen muss das Programm trotzdem
* abgebrochen werden.
  IF substance = 'X'.
    LEAVE PROGRAM.
  ENDIF.

* da es nicht mehr als 20 subscreens geben darf wird der Index bei 15 zurueckgesetzt
  IF sy-lsind > 2.
    sy-lsind = 2.
  ENDIF.

* Holen von X und Y
  GET CURSOR LINE y OFFSET x.

* Für die korrekt umrechnung in Koordinaten muss Y-2 und X+1 gerechnet werden
  IF sy-lsind = 1.
    y = y - 2.
  ENDIF.
  x = x + 1.

* Abfrage was sich auf der geklickten Stelle befindet und schreibe das in Blinder

  PERFORM get_attr USING it_minefield x y
                   CHANGING substance.

  PERFORM set_attr USING x y substance
                   CHANGING blinder.

**********************************************************************************
* wenn auf der geklickten Stelle eine 0 steht, dann sollen alle 8 Felder drumrum *
* auch freigelegt werden, da bei einer 0 keine Mine dort sein kann               *
* REKURSIV werden alle anderen Felder drumrum auch freigelegt                    *
**********************************************************************************

  IF substance = '0'.

   PERFORM copy_all_8 USING x y x y.

  ENDIF.

************************************************************************************************
* wenn weder eine 0 noch eine Mine gefunden wurde, dann prüfe ob gewonnen wurde und stelle     *
* einfach die Tabelle blinder dar.                                                             *
************************************************************************************************

  IF substance <> 'X'.

    z = 0.

    LOOP AT blinder ASSIGNING <blinder_line>.
      DO.
            ASSIGN COMPONENT sy-index OF STRUCTURE <blinder_line> TO <content>.
            IF sy-subrc <> 0. EXIT. ENDIF.
            IF <content> = '#'.
              z = z + 1.
            ENDIF.
      ENDDO.
    ENDLOOP.

*   ES GIBT NUR NOCH DIE MINEN, DAS SPIEL IST GEWONNEN!
    IF z = 9.

      WRITE: / 'Herzlichen Glückwunsch! Sie haben gewonnen!'.
      WRITE: /,/,/.
      substance = 'X'.
      HIDE: substance.
    ENDIF.


*   Gebe die Tabelle Blinder aus und warte auf Eingaben
    LOOP AT blinder ASSIGNING <blinder_line>.
      CONCATENATE
              <blinder_line>-1 <blinder_line>-2 <blinder_line>-3
              <blinder_line>-4 <blinder_line>-5 <blinder_line>-6
              <blinder_line>-7 <blinder_line>-8 <blinder_line>-9
              INTO result.
      WRITE: / result.
    ENDLOOP.


* CHEAT zum testen... :D
********    WRITE: / 'CHEAT': , / , / , / , /.
********
********    LOOP AT it_minefield INTO wa_blinder.
********      WRITE: /
********           wa_blinder-1,
********           wa_blinder-2,
********           wa_blinder-3,
********           wa_blinder-4,
********           wa_blinder-5,
********           wa_blinder-6,
********           wa_blinder-7,
********           wa_blinder-8,
********           wa_blinder-9
********           .
********    ENDLOOP.

  ELSE.

* Wenn X gefunden wurde, soll das Minenfeld ausgegeben werden und das Spiel beendet werden.
    WRITE: / 'Leider haben sie das Spiel verloren!'.
    WRITE: / , / .
    LOOP AT it_minefield ASSIGNING <blinder_line>.
      CONCATENATE
              <blinder_line>-1 <blinder_line>-2 <blinder_line>-3
              <blinder_line>-4 <blinder_line>-5 <blinder_line>-6
              <blinder_line>-7 <blinder_line>-8 <blinder_line>-9
              INTO result.
      WRITE: / result.
    ENDLOOP.
    HIDE: substance.
  ENDIF.

Code:
*&---------------------------------------------------------------------*
*&  Include           Z_MINEFIELD
*&---------------------------------------------------------------------*

*Hier soll das ganze Minenfeld durchlaufen werden, um die Position jeder
*Mine wird die Anzahl in der blinder-Tabelle erhöht. Danach wird die position
*jeder Mine kopiert und dann wird das ganze zurueck auf die Minenfeld-Tabelle geschrieben.

*******************************************************************************************

DO 9 TIMES.
    wa_blinder = '000000000'.
    APPEND wa_blinder TO blinder.
ENDDO.

*******************************************
*        START DES ZEILENDRUCHLAUFES      *
*******************************************
LOOP AT it_minefield ASSIGNING <mine_line>.
  zeile = sy-tabix.

*  durchlaufe alle spalten und suche dabei den Wert X
  DO.
    ASSIGN COMPONENT sy-index OF STRUCTURE <mine_line> TO <content>.
    IF sy-subrc <> 0. EXIT. ENDIF.
    spalte = sy-index.

*   ******************************************************************************
*   *   WENN EINE BOMBE GEFUNDEN IST MÜSSEN ALLE FELDER DARUM UM 1 ERHÖHT WERDEN *
*   ******************************************************************************
    IF <content> = 'X'.

*     Zeile vor der Fundstelle
      zeile = zeile - 1.
      IF zeile > 0.
        CLEAR wa_blinder.
        counter = 0.
        spalte = spalte - 1.

        WHILE counter < spalte.
          counter = counter + 1.
          ASSIGN COMPONENT counter OF STRUCTURE wa_blinder TO <content>.
          IF <content> IS INITIAL.
            <content> = '0'.
          ELSE.
            <content> = <content>.
          ENDIF.
        ENDWHILE.
        spalte = spalte + 1.

        IF spalte = 1.
          counter = 1.
          DO 2 TIMES.
            ASSIGN COMPONENT counter OF STRUCTURE wa_blinder TO <content>.
            IF sy-subrc <> 0. EXIT. ENDIF.
            <content> = <content> + 1.
            counter = counter + 1.
          ENDDO.

        ELSE.
          DO 3 TIMES.
            ASSIGN COMPONENT counter OF STRUCTURE wa_blinder TO <content>.
            IF sy-subrc <> 0. EXIT. ENDIF.
            <content> = <content> + 1.
            counter = counter + 1.
          ENDDO.
        ENDIF.

        DO.
          ASSIGN COMPONENT counter OF STRUCTURE wa_blinder TO <content>.
          IF sy-subrc <> 0. EXIT. ENDIF.
          IF <content> IS INITIAL.
            <content> = '0'.
          ELSE.
            <content> = <content>.
          ENDIF.
          counter = counter + 1.
        ENDDO.

        READ TABLE blinder INDEX zeile ASSIGNING <blinder_line>.

        IF sy-subrc = 0.
          wa_blinder-1 = wa_blinder-1 + <blinder_line>-1.
          wa_blinder-2 = wa_blinder-2 + <blinder_line>-2.
          wa_blinder-3 = wa_blinder-3 + <blinder_line>-3.
          wa_blinder-4 = wa_blinder-4 + <blinder_line>-4.
          wa_blinder-5 = wa_blinder-5 + <blinder_line>-5.
          wa_blinder-6 = wa_blinder-6 + <blinder_line>-6.
          wa_blinder-7 = wa_blinder-7 + <blinder_line>-7.
          wa_blinder-8 = wa_blinder-8 + <blinder_line>-8.
          wa_blinder-9 = wa_blinder-9 + <blinder_line>-9.
        ENDIF.

        MODIFY blinder INDEX zeile FROM wa_blinder.

      ENDIF.
      zeile = zeile + 1.


*     Zeile der Fundstelle
      CLEAR wa_blinder.
      counter = 0.
      spalte = spalte - 1.

      WHILE counter < spalte.
        counter = counter + 1.
        ASSIGN COMPONENT counter OF STRUCTURE wa_blinder TO <content>.
        IF <content> IS INITIAL.
          <content> = '0'.
        ELSE.
          <content> = <content>.
        ENDIF.
      ENDWHILE.
      spalte = spalte + 1.

      IF spalte = 1.
        counter = 1.
        DO 2 TIMES.
          ASSIGN COMPONENT counter OF STRUCTURE wa_blinder TO <content>.
          IF sy-subrc <> 0. EXIT. ENDIF.
          <content> = <content> + 1.
          counter = counter + 1.
        ENDDO.

      ELSE.
         DO 3 TIMES.
          ASSIGN COMPONENT counter OF STRUCTURE wa_blinder TO <content>.
          IF sy-subrc <> 0. EXIT. ENDIF.
          <content> = <content> + 1.
          counter = counter + 1.
        ENDDO.
      ENDIF.

      DO.
        ASSIGN COMPONENT counter OF STRUCTURE wa_blinder TO <content>.
        IF sy-subrc <> 0. EXIT. ENDIF.
        IF <content> IS INITIAL.
          <content> = '0'.
        ELSE.
          <content> = <content>.
        ENDIF.
        counter = counter + 1.
      ENDDO.

      READ TABLE blinder INDEX zeile ASSIGNING <blinder_line>.

      IF sy-subrc = 0.
        wa_blinder-1 = wa_blinder-1 + <blinder_line>-1.
        wa_blinder-2 = wa_blinder-2 + <blinder_line>-2.
        wa_blinder-3 = wa_blinder-3 + <blinder_line>-3.
        wa_blinder-4 = wa_blinder-4 + <blinder_line>-4.
        wa_blinder-5 = wa_blinder-5 + <blinder_line>-5.
        wa_blinder-6 = wa_blinder-6 + <blinder_line>-6.
        wa_blinder-7 = wa_blinder-7 + <blinder_line>-7.
        wa_blinder-8 = wa_blinder-8 + <blinder_line>-8.
        wa_blinder-9 = wa_blinder-9 + <blinder_line>-9.
      ENDIF.

      MODIFY blinder INDEX zeile FROM wa_blinder.
      zeile = zeile + 1.


*     Zeile nach Fundstelle

      IF zeile <= 9.
        CLEAR wa_blinder.
        counter = 0.
        spalte = spalte - 1.

        WHILE counter < spalte.
          counter = counter + 1.
          ASSIGN COMPONENT counter OF STRUCTURE wa_blinder TO <content>.
          IF <content> IS INITIAL.
            <content> = '0'.
          ELSE.
            <content> = <content>.
          ENDIF.
        ENDWHILE.
        spalte = spalte + 1.

        IF spalte = 1.
          counter = 1.
          DO 2 TIMES.
            ASSIGN COMPONENT counter OF STRUCTURE wa_blinder TO <content>.
            IF sy-subrc <> 0. EXIT. ENDIF.
            <content> = <content> + 1.
            counter = counter + 1.
          ENDDO.

        ELSE.
          DO 3 TIMES.
            ASSIGN COMPONENT counter OF STRUCTURE wa_blinder TO <content>.
            IF sy-subrc <> 0. EXIT. ENDIF.
            <content> = <content> + 1.
            counter = counter + 1.
          ENDDO.
        ENDIF.

        DO.
          ASSIGN COMPONENT counter OF STRUCTURE wa_blinder TO <content>.
          IF sy-subrc <> 0. EXIT. ENDIF.
          IF <content> IS INITIAL.
            <content> = '0'.
          ELSE.
            <content> = <content>.
          ENDIF.
          counter = counter + 1.
        ENDDO.

      ENDIF.

      READ TABLE blinder INDEX zeile ASSIGNING <blinder_line>.

      IF sy-subrc = 0.
        wa_blinder-1 = wa_blinder-1 + <blinder_line>-1.
        wa_blinder-2 = wa_blinder-2 + <blinder_line>-2.
        wa_blinder-3 = wa_blinder-3 + <blinder_line>-3.
        wa_blinder-4 = wa_blinder-4 + <blinder_line>-4.
        wa_blinder-5 = wa_blinder-5 + <blinder_line>-5.
        wa_blinder-6 = wa_blinder-6 + <blinder_line>-6.
        wa_blinder-7 = wa_blinder-7 + <blinder_line>-7.
        wa_blinder-8 = wa_blinder-8 + <blinder_line>-8.
        wa_blinder-9 = wa_blinder-9 + <blinder_line>-9.
      ENDIF.

      MODIFY blinder INDEX zeile FROM wa_blinder.
      zeile = zeile - 1.

    ENDIF. "Ende von IF <content> = 'X'

  ENDDO.   "ENDE von durchlaufe alle spalten und suche X Zeile 18

ENDLOOP.


***********************************************************************************
* AB HIER HABEN WIR ALLE FELDER MIT DER RICHTIGEN ANZAHL AN MINEN DRUMRUM BELEGT  *
* NUN KOPIEREN WIR DIE LAGE DER MINEN IN BLINDER UM EIN FERTIGES BILD ZU ERHALTEN *
***********************************************************************************

*  durchlaufe alle Zeilen
LOOP AT it_minefield ASSIGNING <mine_line>.
  zeile = sy-tabix.
*  durchlaufe alle spalten und suche dabei den Wert X
  DO.
    ASSIGN COMPONENT sy-index OF STRUCTURE <mine_line> TO <content>.
    IF sy-subrc <> 0. EXIT. ENDIF.
    spalte = sy-index.
    IF <content> = 'X'.
*     schreibe in die Bl#nder ein X an die Stelle
      PERFORM set_attr USING spalte zeile <content>
                       CHANGING blinder.
    ENDIF.
  ENDDO.
ENDLOOP.

*********************************************************************
* HIER WIRD DAS FERTIGE BLINDER-ERGEBNIS AUF DAS MINENFELD KOPIERT! *
*********************************************************************
MOVE blinder TO it_minefield.

Code:
*&---------------------------------------------------------------------*
*&  Include           Z_MINE_FUNCTIONS
*&---------------------------------------------------------------------*

************************************************************************
* suche den Inhalt an der Stelle X/Y heraus und gebe ihn zurueck.
************************************************************************

FORM get_attr USING it_table TYPE tt_minefield_ty
                      x_temp TYPE i
                      y_temp TYPE i
              CHANGING
                      inhalt TYPE c
                      .

  FIELD-SYMBOLS: <table_line> TYPE tt_minefield,
                 <temp_content> TYPE c.

  LOOP AT it_table ASSIGNING <table_line>.
    IF sy-tabix = y_temp.
      DO.
        ASSIGN COMPONENT sy-index OF STRUCTURE <table_line> TO <temp_content>.
        IF sy-subrc <> 0. EXIT. ENDIF.
        IF sy-index = x_temp.
          inhalt = <temp_content>.
        ENDIF.
      ENDDO.
    ENDIF.
  ENDLOOP.
ENDFORM. "get_xyattr

************************************************************************
* setze den Inhalt an der Stelle X,Y auf den Wert von Inhalt           *
************************************************************************

FORM set_attr USING
                      x_temp TYPE i
                      y_temp TYPE i
                      inhalt TYPE c
              CHANGING
                      it_table TYPE tt_minefield_ty
                      .

  FIELD-SYMBOLS: <table_line> TYPE tt_minefield,
                 <temp_content> TYPE c.

  LOOP AT it_table ASSIGNING <table_line>.
    IF sy-tabix = y_temp.
      DO.
        ASSIGN COMPONENT sy-index OF STRUCTURE <table_line> TO <temp_content>.
        IF sy-subrc <> 0. EXIT. ENDIF.
        IF sy-index = x_temp.
          <temp_content> = inhalt.
        ENDIF.
      ENDDO.
    ENDIF.
  ENDLOOP.

ENDFORM. "set_attr

******************************************************************************
* Durchsuche die Tabelle nach dem Inhalt von inhalt und gebe x und y zurueck *
******************************************************************************

FORM search_table USING it_table TYPE tt_minefield_ty
                        inhalt TYPE c
                  CHANGING
                        x_temp TYPE i
                        y_temp TYPE i
                        .
  FIELD-SYMBOLS: <table_line> TYPE tt_minefield,
                 <temp_content> TYPE c.

  LOOP AT it_table ASSIGNING <table_line>.
    DO.
      ASSIGN COMPONENT sy-index OF STRUCTURE <table_line> TO <temp_content>.
      IF sy-subrc <> 0. EXIT. ENDIF.
      IF <temp_content> = inhalt.
        x_temp = sy-index.
        y_temp = sy-tabix.
      ENDIF.
    ENDDO.
  ENDLOOP.

ENDFORM. "search_table


*******************************************************************************
*                   Fülle eine Tabelle mit einem Wert                         *
*******************************************************************************

FORM fill_table USING inhalt TYPE c
                CHANGING it_table TYPE tt_minefield_ty.

  FIELD-SYMBOLS: <table_line> TYPE tt_minefield,
                 <temp_content> TYPE c.

  LOOP AT it_table ASSIGNING <table_line>.
    DO.
      ASSIGN COMPONENT sy-index OF STRUCTURE <table_line> TO <temp_content>.
      IF sy-subrc <> 0. EXIT. ENDIF.
      <temp_content> = inhalt.
    ENDDO.
  ENDLOOP.

ENDFORM. "fill_table

*******************************************************************************
*               Kopiere die 8 Stellen um eine Stelle x,y                      *
*******************************************************************************

*Übergeben werden: formx = die X-Variable der Stelle um die gesucht werden soll
*                  formy = die Y-Variable der Stelle um die gesucht werden soll
*                  oldx  = die X-Variable von der aus aufgerufen wur#e
*                  oldy  = die Y-Variable von der aus aufgerufen wurde

FORM copy_all_8 USING formx TYPE i
                           formy TYPE i
                           oldx TYPE i
                           oldy TYPE i
                          .

  DATA: tempx TYPE i,              "beinhaltet den aktuellen X-Wert in der Schleife
        tempy TYPE i,              "beinhaltet den aktuellen Y-Wert in der Schleife
        temp_substance TYPE c,     "enthält den gefunden Wert auf der Stelle tempx/tempy auf der it_minenfeld
        temp_blinder TYPE c,       "enthält den gefunden Wert auf der Stelle tempx/tempy auf der blinder
        run TYPE i VALUE 3         "Lauflänge der Loop-Schleifen
        .

* zeichne die drei stellen über der 0
  tempy = formy - 1.
  tempx = formx - 1.

  IF tempy > 0.

    DO run TIMES.

      PERFORM get_attr USING it_minefield tempx tempy
                       CHANGING temp_substance.

      PERFORM get_attr USING blinder tempx tempy
                       CHANGING temp_blinder.

      IF     temp_substance = '0'
         AND temp_blinder = '#'
         AND NOT ( tempx = oldx AND tempy = oldy )
         AND NOT ( tempx = formx AND tempy = formy )
         .

        PERFORM set_attr USING tempx tempy temp_substance
                 CHANGING blinder.

*REKURSION!*
        PERFORM copy_all_8 USING tempx tempy formx formy.
************

      ELSE.

        PERFORM get_attr USING it_minefield tempx tempy
                       CHANGING temp_substance.

        PERFORM set_attr USING tempx tempy temp_substance
                 CHANGING blinder.

      ENDIF.

      tempx = tempx + 1.

    ENDDO.
  ENDIF.

* zeichne die drei stellen bei der 0
  tempy = formy.
  tempx = formx - 1.

  DO run TIMES.

    PERFORM get_attr USING it_minefield tempx tempy
                     CHANGING temp_substance.

    PERFORM get_attr USING blinder tempx tempy
                       CHANGING temp_blinder.

    PERFORM set_attr USING tempx tempy temp_substance
                  CHANGING blinder.

    IF     temp_substance = '0'
         AND temp_blinder = '#'
         AND NOT ( tempx = oldx AND tempy = oldy )
         AND NOT ( tempx = formx AND tempy = formy )
         .

      PERFORM set_attr USING tempx tempy temp_substance
                  CHANGING blinder.

*REKURSION!*
        PERFORM copy_all_8 USING tempx tempy formx formy.
************

    ELSE.

      PERFORM set_attr USING tempx tempy temp_substance
               CHANGING blinder.

    ENDIF.

    tempx = tempx + 1.
  ENDDO.


* zeichne die drei Stellen unter der 0
  tempy = formy + 1.
  tempx = formx - 1.
  IF tempy < 10.

    DO run TIMES.
      PERFORM get_attr USING it_minefield tempx tempy
                       CHANGING temp_substance.

      PERFORM get_attr USING blinder tempx tempy
                       CHANGING temp_blinder.

      IF     temp_substance = '0'
         AND temp_blinder = '#'
         AND NOT ( tempx = oldx AND tempy = oldy )
         AND NOT ( tempx = formx AND tempy = formy )
         .

        PERFORM set_attr USING tempx tempy temp_substance
                 CHANGING blinder.

*REKURSION!*
        PERFORM copy_all_8 USING tempx tempy formx formy.
************

      ELSE.

        PERFORM set_attr USING tempx tempy temp_substance
                 CHANGING blinder.

      ENDIF.

      tempx = tempx + 1.
    ENDDO.
  ENDIF.
ENDFORM. "copy_all_8

Code:
*&---------------------------------------------------------------------*
*&  Include           Z_BUILD_MINEFIELD
*&---------------------------------------------------------------------*

************************************************************************
*                    FÜLLE DAS MINENFELD MIT 0en                       *
************************************************************************


  DO 9 TIMES.
    wa_minefield = '000000000'.
    APPEND wa_minefield TO it_minefield.
  ENDDO.


***********************************************************************
*                schreibe 10 Minen in das Feld                        *
***********************************************************************

GET run time FIELD result.

DO 9 TIMES.

************************************************************************
*                  Erzeuge RANDOM Werte                                *
************************************************************************

* RANDOM y-Wert
  WHILE y = 0.
    GET run time FIELD result.
    y = strlen( result ).
    y = y - 2.
    y = result+y.
  ENDWHILE.

* Wartezeit, damit x <> y
  DO 2 TIMES.
    GET run time FIELD result.
      z = strlen( result ).
      z = z - 3.
      z = result+z.
    DO z TIMES.
    ENDDO.
  ENDDO.

*   erzeuge RANDOM Zahl x
  WHILE x = 0.
    GET run time FIELD result.
    x = strlen( result ).
    x = x - 2.
    x = result+x.
  ENDWHILE.

* schreibe X an die Stelle x,y

  PERFORM set_attr USING x y 'X'
                CHANGING it_minefield.

* Reset der Werte
  x = 0.
  y = 0.
ENDDO.

counter = 0.
 
Meine Lösung

Hier ist meine Lösung in C

Das ganze habe ich der Übersichtlichkeit halber in verschiedene Dateien gesplittet.

Hauptprogramm
Code:
#include <stdio.h>
#include <stdlib.h>
#include "funktionen.h"
#include "Test.h" /* Zum Testen! */

/*
    - Ein einfaches Spielfeld 8x8 mit 10 Minen (16%). **
        - Zwei Matrizen a 8x8. ***
        - In der einen sind die Positionen der
          Minen gespeichert.***
        - In der anderen Matrize ist gespeichert
          welches Feld bereits aufgedeckt wurde. ***
        - Die Matrizen werden global angelegt. ***
    - Jedes freie Feld soll wissen, wie viele Minen in
      seiner unmittelbaren Umgebung liegen. ***
    - Optional: Möglichkeit Felder zu markieren!


*/

int posMinen[8][8];
int aufgedeckteMinen[8][8];
int countFreieFelder=0;
/*int countExplodierteMinen =0;*/


int main(void) {
    
/*    - Menü mit folgenden Wahlmöglichkeiten:
        - aufdecken eines Feldes.
        - markieren eines Feldes.
        - Lösung anzeigen. 
    - Während des Spielbetriebs soll Zeitphase
      (10 Minuten) getestet werden. 

*/
    
    anlegenSpielfeld();
    positioniereMinen();

    int start = time(0),ende,sekunden=0; /* Erfassung des Startzeitpunktes*/
    int eingabe=1,x,y;
    ausgabeAufgedeckteMinen();
    
    while (eingabe) {
        if (gewonnen()) { /* Hat der Spieler/in schon gewonnen? */
            printf("Sie haben gewonnen nach %d Sekunden! \n",sekunden);
            exit(0);    
}
        printf("\n");
        printf("(0) beenden - (1) aufdecken - (2) markieren - (3) Lösung\n");
        printf("Sie haben noch %d Minuten Zeit\n",(600-sekunden)/60);
        scanf("%d\n",&eingabe);    
        ende = time(0);
        sekunden = ende-start;
        if (sekunden >= 600) break; 
        fflush(stdin);
        
        switch(eingabe) {
            case 0: break;
            
            case 1: printf("\n");
                printf("Koordinaten angeben: ");
                scanf("%d %d",&x,&y);
                printf("\n");
                aufdecken(x,y); /* Lässt Spielfeld automatisch neu erstellen */
                printf("\n");
                break;
            case 2: printf("\n");
                printf("Koordinaten angeben: ");
                scanf("%d %d",&x,&y);
                printf("\n");
                markieren(x,y);
                printf("\n");
                break;
            case 3: ausgabePositionen();
                exit(0);
            default: printf("Falsche Eingabe!\n");
                
        
                



}
        

}

    printf("Das Spiel ist nach %d Sekunden vorbei!\n",sekunden);

    exit(0);
}

Header-Datei
Code:
#ifndef __funktionen__H
#define __funktionen__H


void anlegenSpielfeld(); /* Initalisiert alles mit Null
eigentlich überflüssig! */

void ausgabeAufgedeckteMinen(); /* Müsste eigentlich 
ausgabeAufgedeckteFelder heißen. Da diese Prozedur alle
Felder ausgibt (ihren Status) */

void positioniereMinen(); /* Positioniert zufällig 10 Minen */

void ausgabePositionen(); /* Gibt die Positionen der Minen auf
dem Feld aus. Einaml für mich zum Testen und einmal um eine Lösung 
auszugeben! */

void aufdecken(int,int); /* Damit werden die Felder einzelen
anhand ihrer x und y Koordinate aufgedeckt. */

int nachbarn(int,int); /* Gibt die Anzahl der in der Nachbarschaft
liegenden Minen zurück.  */

void markieren(int , int); /* Damit lassen sich einzelene
Felder (x/y Koordinate) markieren. Vorausgesetzt die Felder
sind noch verdeckt ( - ) ! */

int gewonnen(); /* Dient dazu zu prüfen ob der Spieler/in 
gewonnen hat. Also ob alle freien Felder aufgedeckt wurden */

int countdown(); /* Prüft die Zeit (max 10 Min) */

#endif


Implementierung

Code:
#include <stdio.h>
#include <stdlib.h> 
#include <time.h>

extern int aufgedeckteMinen[8][8];  /*Haben wir bereits in der Hauptdatei */
extern int posMinen[8][8];
extern int countFreieFelder;
extern int start;

/*extern int countExplodierteMinen;*/

/*
    Minen werden mit * dargestellt freie Felder mit O

*/

void anlegenSpielfeld() {
    int i,j;
    for (i=0; i < 8; i++) {
        for (j=0; j < 8; j++) {
            aufgedeckteMinen[i][j] = 0;
}
        
}
}

void ausgabeAufgedeckteMinen() { /* Eigentlich müsste es Felder heißen! */
/*
    0 codiert ein verdecktes Feld
    10 codiert ein Minenfeld somit bumm!
    11 codiert ein allgemein freies Feld.
    1 bis 8 codieren ein aufgedecktes Feld
    mit 1 bis 8 Minen in der Umgebung. 

    Ausgabe:
    - ist ein bedecktes Feld 
    b aufgedecktes Feld mit Mine (bumm!)
    f aufgedecktes allgemein freies Feld.
    x Feld ist markiert! 

*/
    
    int i,j;
    printf("\n");
    for (i=0; i < 8; i++) {
        for(j=0; j < 8; j++) {
            switch (aufgedeckteMinen[i][j]) {
                case 0: printf(" - ");
                    break;
                case 10: printf(" b ");
                    break;
                case 11: printf(" f ");
                     break;
                case 12: printf(" x ");
                     break;
                default: printf(" %d ",aufgedeckteMinen[i][j]);
            

}
}
        printf("\n");
}
    printf("\n");
}


void positioniereMinen() {
    srand(time(0));
    int status = rand() % 2;
    int i,count=0;
    for (i=0; i< 10; i++) {
        /* printf("%d \n",i); */ 
        posMinen[rand() %8][rand() %8] = 1;
        
}
}

void ausgabePositionen() {
/* 
    Mine ist *
    Keine Mine ist O

*/
    int i,j;
    for (i=0; i < 8; i++) {
        for(j=0; j < 8; j++) {
            if (posMinen[i][j]) {
                printf(" * ");
}
            else {
                printf(" O ");
}
}
        printf("\n");
}
}

void aufdecken(int x, int y) {
    if (posMinen[x][y]) {
        aufgedeckteMinen[x][y] = 10;
        ausgabeAufgedeckteMinen();
        printf("Sie haben verloren!\n\n");
        exit(0); /* Da eine Mine explodierte!*/
}
    else {
        aufgedeckteMinen[x][y] = nachbarn(x,y);
        countFreieFelder++;
        ausgabeAufgedeckteMinen();
}
}

/* Die Funktion nachbarn liefert die Anzahl der Nachbarn in der Umgebung! */
int nachbarn(int x, int y) { 
    int X=x,Y=y;
    int i,count=0;

        /* 1. obere Diagonale*/
        X++;
        Y++;
        if (!(( X>7) || (Y>7))) {

        if (posMinen[X][Y]) count++; 
}

    X=x; /* Neu Initalsierung!!! */
    Y=y;

     /* 1. untere Diagonale*/
        X--;
        Y--;
        if (!(( X<0) || (Y<0))) {

        if (posMinen[X][Y]) count++; 
}

    X=x; /* Neu Initalsierung!!! */
    Y=y;

    /* 2 . untere Diagonale*/
    Y++;
    X--;
    if ((X>=0 && X<=7) && (Y>=0 && Y<=7)) {
        if (posMinen[X][Y]) count++;
}

    X=x; /* Neu Initalsierung!!! */
    Y=y;
    
    /* 2 . obere Diagonale*/
    Y--;
    X++;
    if ((X>=0 && X<=7) && (Y>=0 && Y<=7)) {
        if (posMinen[X][Y]) count++;
}


    X=x; /* Neu Initalsierung!!! */
    Y=y;

    /* 1. Fall */
    X++;
    if (X>=0 && X<=7) {
        if (posMinen[X][Y]) count++;
}

    X=x; /* Neu Initalsierung!!! */
    Y=y;

    /* 2. Fall */
    X--;
    if (X>=0 && X<=7) {
        if (posMinen[X][Y]) count++;
}

    X=x; /* Neu Initalsierung!!! */
    Y=y;

    /* 3. Fall */
    Y++;
    if (Y>=0 && Y<=7) {
        if(posMinen[X][Y]) count++;
}

    X=x; /* Neu Initalsierung!!! */
    Y=y;

    /* 4. Fall */
    Y--;
    if (Y>=0 && Y<=7) {
        if(posMinen[X][Y]) count++;
}


    if (count ==0) count = 11; 
    /* Da die Null schon reserviert ist in ausgabeAufgedeckteMinen() */
    return count;
}

void markieren(int x, int y) {
    if ((x>=0 && x<=7) && (y>=0 && y<=7)) { /* Schutzmaßnahme! */ 
        if (aufgedeckteMinen[x][y] == 0) { /* Zugedeckt! */
            aufgedeckteMinen[x][y] = 12; /* Markiert! */
            ausgabeAufgedeckteMinen();
}
}
}

int gewonnen() { 
    return countFreieFelder == 54;
}

int countdown() {
    
}


Mit freundlichen Grüßen

Christian
 
Zurück
Oben