Schweizer Käse

Hi,da die letzte Aufgabe zugegebenermaßen langweilig war hier eine neue:

AUFGABE:
Stellen wir uns ein würfelförmiges Stück Schweizer Käse
vor. Wir modellieren den Käse durch ein 20x20x20-Raster.
Vereinfachend gehen wir davon aus, dass jeder Rasterwürfel
ganz aus Käse oder ganz aus Luft besteht. Auf
die obere Seite unseres Schweizer Käsewürfels wird nun
Wasser gegossen, welches dann nur durch die Luftlöcher
in den Würfel eindringt und ihn möglicherweise auf
einem durchgängigen Kanal von der Oberseite bis zur
Unterseite durchfließt. Dabei kann von einem Luftwürfel
zum nächsten nur dann Wasser fließen, wenn die beiden
Luftwürfel eine ganze Seite gemeinsam haben (nicht
nur eine Kante oder eine Ecke). Das Wasser kann auch auf
?Umwegen? fließen wie z.B. beim Siphon eines Waschbeckenabflusses.
Schreibe ein Programm, das einen Würfel mit einer
zufälligen Verteilung von Luft- und Käserasterwürfeln
erzeugt, bei der die Wahrscheinlichkeit für Käse p% und
für Luft q%(100-p) beträgt, und prüft, ob aus dem Würfel
unten Wasser herauskommt.
p soll vom User abgefragt werden.

Happy Coding,
Xalon

P.S:Schwierigkeit ist imo bei 2.5 anzusiedeln ;-)
 
Code:
#include <stdio.h>
#include <time.h>
#include <windows.h>


#define X 20
#define Y 20
#define Z 20

typedef enum
{
 
  KAESE = 1,
  LUFT,
  WASSER
 
} ZUSTAND;

int Kaese[X][Y][Z];

int firstsurface[X][Y];
int secondsurface[X][Y];

int backupsurface[X][Y];

void Init(p)
    int p;
{
  int x, y, z;
  
  srand(time(NULL));
 
  for(x = 0; x < X; ++x)
    for(y = 0; y < Y; ++y)
      for(z = 0; z < Z; ++z)
      {
        if((rand() % 100) < p)     
          Kaese[x][y][z] = KAESE;
        else        
          Kaese[x][y][z] = LUFT;
      }

  for(x = 0; x < X; ++x)
    for(z = 0; z < Z; ++z)
      backupsurface[x][z] = WASSER;
}

void ClearSurface(surface)
    int (*surface)[Y];
{
    int x, z;
  for(x = 0; x < X; ++x)
    for(z = 0; z < Z; ++z)
      surface[x][z] = 0;
}

void ShowSurface(surface)
    int (*surface)[Y];
{
  HANDLE hStdout;
  int x, z;
  hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
 
  for(x = 0;  x < X; ++x)
  {
    for(z = 0; z < Z; ++z)
    {
      if(surface[x][z] == WASSER)
      {
        SetConsoleTextAttribute(hStdout, FOREGROUND_BLUE);
        printf("~");
      }
      if(surface[x][z] == LUFT)
      {
        SetConsoleTextAttribute(hStdout, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
        printf(" ");
      }
      if(surface[x][z] == KAESE)
      {
        SetConsoleTextAttribute(hStdout, FOREGROUND_RED | FOREGROUND_GREEN);
        printf("*");
      }
    }
    printf("\n");
  }
}

void ScanSurface(y, surface)
    int y;
    int (*surface)[Z];
{
    int x, z;
  for(x = 0; x < X; ++x)
  {
    for(z = 0; z < Z; ++z)
    {
      if(Kaese[y][x][z] == LUFT)
        surface[x][z] = LUFT;
     
      if(Kaese[y][x][z] == WASSER)
        surface[x][z] = WASSER;
     
      if(Kaese[y][x][z] == KAESE)
        surface[x][z] = KAESE;
    }
  }
}

void GrowWater(surface)
    int (*surface)[Y];
{
    int i, y, x;
    int t_x, t_y;
  for(i = 0; i < 10; ++i)
    for(y = 0; y < Y; ++y)
    {
      for(x = 0; x < X; ++x)
      {
        if(surface[y][x] == WASSER)
        {
          // LINKS
          t_x = x;
          while(t_x >= 0 && ((surface[y][t_x] == WASSER || surface[y][t_x] == LUFT)))
          {
            surface[y][t_x] = WASSER;
            t_x--;
          }
          // RECHTS
          t_x = x;
          while(t_x < X && ((surface[y][t_x] == WASSER || surface[y][t_x] == LUFT)))
          {
            surface[y][t_x] = WASSER;
            t_x++;
          }
          // OBEN
          t_y = y;
          while(t_y >= 0 && ((surface[t_y][x] == WASSER || surface[t_y][x] == LUFT)))
          {
            surface[t_y][x] = WASSER;
            t_y--;
          }
          // UNTEN
          t_y = y;
          while(t_y < Y && ((surface[t_y][x] == WASSER || surface[t_y][x] == LUFT)))
          {
            surface[t_y][x] = WASSER;
            t_y++;
          }
        }
      }
    }
}

void CheckSurfaces(fsurface, ssurface)
    int (*fsurface)[Y];
    int (*ssurface)[Y];
{
    int x, y, z;
 
  for(y = 0; y < Y; ++y)
  {
    for(x = 0; x < X; ++x)
    {
      if(backupsurface[y][x] == WASSER)
      {
        if(fsurface[y][x] == LUFT) {
          fsurface[y][x] = WASSER;
        }
      }
    }
  }
  GrowWater(fsurface);
  
  for(y = 0; y < Y; ++y)
  {
    for(x = 0; x < X; ++x)
    {
      if(fsurface[y][x] == WASSER)
      {
        if(ssurface[y][x] == LUFT) {
         
          ssurface[y][x] = WASSER;
        }
      }
    }
  }
 
  GrowWater(ssurface);
  
  for(x = 0; x < X; ++x)
    for(z = 0; z < Z; ++z)
      backupsurface[x][z] = ssurface[x][z];
}

void Search(void)
{
  int y = 0;
 
  while(y < 20)
  {
    ScanSurface(y, firstsurface);
    y++;

    ScanSurface(y, secondsurface);

    CheckSurfaces(firstsurface, secondsurface);
   

    printf("\n\n%i Schicht\n\n", y);
    ShowSurface(firstsurface);
    y++;
    printf("\n\n%i Schicht\n\n", y);
    ShowSurface(secondsurface);
    getchar();

    ClearSurface(firstsurface);
    ClearSurface(secondsurface);
  }
}

int main(int argc, char *argv[])
{
  Init(60);
  Search();
  getchar();
}
 
Code:
#include <iostream>
#include <stdlib.h>
#include <time.h>

using namespace std;

enum Inhalt { LUFT, WASSER, KAESE };

enum Inhalt stueck[20][20][20];

void init(int p)
{
	for(int x = 0 ; x < 20 ; x++)
		for(int y = 0 ; y < 20 ; y++)
			for(int z = 0 ; z < 20 ; z++)
				if(rand() % 101 <= p)
					stueck[x][y][z]=KAESE;
				else
					stueck[x][y][z]=LUFT;
}

void print()
{
	for(int y = 0 ; y < 20 ; y++) {
		cout << "   Schicht " << y+1 << endl;
		cout << ",-----------------------------------------," << endl;
		for(int x = 0 ; x < 20 ; x++) {
			cout << "| ";
			for(int z = 0 ; z < 20 ; z++)
				if(stueck[x][y][z] == KAESE)
					cout << "X ";
				else if(stueck[x][y][z] == LUFT)
					cout << "  ";
				else if(stueck[x][y][z] == WASSER)
					cout << "O ";
			cout << "|" << endl;
		}
		cout << "`-----------------------------------------´" << endl;
	}
}

int check(int x, int y, int z)
{
	if(stueck[x][y][z] == LUFT)
	{
		stueck[x][y][z] = WASSER;
		int i=0;
		if(x < 19) i+=check(x+1, y, z);
		if(x >  0) i+=check(x-1, y, z);
		if(y < 19) i+=check(x, y+1, z);
		if(y >  0) i+=check(x, y-1, z);
		if(z < 19) i+=check(x, y, z+1);
		if(z >  0) i+=check(x, y, z-1);
		if(y == 19)
			return(1);
		return(i>0);
	}
	return(0);
}

int main()
{
	srand(time(0));

	int p;
	do {
		cout << "Wahrscheinlichkeit fuer Kaese (1...99): " << flush;
		cin >> p;
	} while(p < 1 || p > 99);

	init(p);

//	print();

	p=0;
	for(int x = 0 ; x < 20 ; x++)
		for(int z = 0 ; z < 20 ; z++)
			p+=check(x, 0, z);

	if(p)
		cout << "Wasser ist durchgelaufen!" << endl;
	else
		cout << "Der Kaeseblock war wasserdicht!" << endl;

//	print();

	return(0);
}
 
Hallo,

da ich heute auch mal wieder etwas Zeit hatte, habe ich das ganze mal ausprogrammiert, zuerst nur als Konsolen-Anwendung jetzt dann doch noch mit grafischer Oberfläche.

Alles ist in C# 2003 geschrieben.

Den Code, der sogut wie auch sofort als Konsolen-Anwendung laufen müsste (wenige Änderungen) poste ich gleich hier.

Mit GUI und grafischer Auswertung des Käses, wodurch ein "scrollen" durch die Käse-Ebenen möglich wird, poste ich es 1. als vollständiges Projekt und 2. als kompilierte .exe (beides in einem .rar-archiv).

Die Bedienung dürfte intuitiv erfahrbar sein. Durch maus-clicks bzw. das drehen am mausrad verändert man die Ebene (Z-Koordinate).

Ihr könnt das gerne noch erweitern.

Viel Spaß mitm Code, ich habe mich bemüht ihn einigermaßen zu kommentieren und passende Variablen-Namen zu wählen.

Den Rest des Codes für die grafische Oberfläche findet ihr im Archiv. Fände es nicht sinnvoll, den hier zu posten.

Code:
using System;
namespace schweizer_kaese
{
/// <summary>
/// written by Subfreq aka Matthias Rost
/// </summary>
class KaeseWuerfel
{
public static int X = 20;
public static int Y = 20;
public static int Z = 20;

public enum zustand
{
Kaese,
Luft,
Wasser
}
//Der Käse
public zustand[,,] wuerfel = new zustand[X,Y,Z];

public bool wasser_gefunden = false;

/// <summary>
/// Der Haupteinstiegspunkt für die Anwendung.
/// Parameter: Wahrscheinlichkeit für Käse
/// </summary>
public void start(int p)
{
//Der Wuerfel wird "erzeugt"
init_wuerfel(p);
//Die Oberfläche ( [0..19][0..19][19] ) wird geflutet
flute_oberflaeche();
//Teste ob der Boden Elemente mit Wasser enthält
teste_boden();

}
/// <summary>
/// Initialisiert den Würfel, ergibt wahrscheinlichkeits-
/// verteilung von käse und Luft
/// </summary>
/// <param name="p">Wahrscheinlichkeit für Käse</param>
private void init_wuerfel(int p)
{
Random zufallgen = new Random();
for(int x = 0; x < X; x++)
{
for(int y = 0; y < Y; y++)
{
for(int z = 0; z < Z; z++)
{
if(zufallgen.Next(1,100) <= p)
{
wuerfel[x,y,z] = zustand.Kaese;
}
else
{
wuerfel[x,y,z] = zustand.Luft;
}
}
}
}
}
/// <summary>
/// flutet die Oberflaeche des Wuerfels
/// </summary>
private void flute_oberflaeche()
{
int z = Z-1;
for(int x = 0; x < X; x++)
{
for(int y = 0; y < Y; y++)
{
test_setze_verbreit(x,y,z);
}
}
}

private void verbreite_wasser(int x,int y, int z)
{
//Ist man am Boden angekommen, kann es nicht noch tiefer gehen
if(z > 0)
{
test_setze_verbreit(x,y,z-1);
}
if(z < Z-1)
{
test_setze_verbreit(x,y,z+1);
}
for(int dx = x-1; dx < x+2; dx = dx + 2)
{
//Test, ob man außerhalb des Würfels gelandet wäre
if(dx > -1 && dx < X)
{
test_setze_verbreit(dx,y,z);
}
}
for(int dy = y-1; dy < y+2; dy = dy + 2)
{
//Test, ob man außerhalb des Würfels gelandet wäre
if(dy > -1 && dy < Y)
{
test_setze_verbreit(x,dy,z);
}
}
}

/// <summary>
/// Diese Funktion überprüft, ob an der angegbenen Position Luft vorhanden ist
/// Falls ja, wird der Zustad auf Wasser gesetzt und die Umgebung geflutet.
/// </summary>
private void test_setze_verbreit(int x, int y, int z)
{
if(wuerfel[x,y,z] == zustand.Luft)
{
wuerfel[x,y,z] = zustand.Wasser;
verbreite_wasser(x,y,z);
}
}

private void teste_boden()
{
int z = 0;
for(int x = 0; x < X; x++)
{
for(int y = 0; y < Y; y++)
{
if(wuerfel[x,y,z] == zustand.Wasser)
{
wasser_gefunden = true;
}
}
}
if(wasser_gefunden)
{
System.Console.WriteLine("Das Wasser laeuft unten heraus.\nDer Wuerfel ist durchlaessig!");
}
else
{
System.Console.WriteLine("Es laeuft kein Wasser aus.\nDer Wuerfel ist nicht durchlaessig!");
}
Console.ReadLine();
}

}
}
Grüße,Subfreq
 
Zurück
Oben